Adding custom queries to managers is the Django convention. From the Django docs on custom managers:
Adding extra Manager methods is the preferred way to add “table-level” functionality to your models.
If it’s your own private app, the convention word doesn’t matter so much – indeed my company’s internal codebase has a few classmethods that perhaps belong in a custom manager.
However, if you’re writing an app that you’re going to share with other Django users, then they’ll expect to see findBy on a custom manager.
I don’t think the inheritance issues you mention are too bad. If you read the custom managers and model inheritance docs, I don’t think you’ll get caught out. The verbosity of writing .objects is bearable, just as it is when we do queries using XYZ.objects.get() and XYZ.objects.all()
Here’s a few advantages of using manager methods in my opinion:
-
Consistency of API. Your method
findBybelongs withget,filter,aggregateand the rest. Want to know what lookups you can do on theXYZ.objectsmanager? It’s simple when you can introspect withdir(XYZ.objects). -
Static methods “clutter” the instance namespace.
XYZ.findBy()is fine but if you define a static method, you can also doxyz.findBy(). Running thefindBylookup on a particular instance doesn’t really make sense. -
DRYness. Sometimes you can use the same manager on more than one model.
Having said all that, it’s up to you. I’m not aware of a killer reason why you should not use a static method. You’re an adult, it’s your code, and if you don’t want to write findBy as a manager method, the sky isn’t going to fall in 😉
For further reading, I recommend the blog post Managers versus class methods by James Bennett, the Django release manager.