The original question: Why aren’t Managers and QuerySets one thing?
After digging through the project I’ve been thinking of, the Django source code, and some old tickets, I think I found the answer that most satisfies me.
Answer: Originally they were.
In the beginning were Managers. For about 10 years (until version 1.7) there were officially only Managers for creating custom queryset methods.
It was version 1.7 that formally documented the creation and usage of a separate QuerySet class for adding custom QuerySet methods. (The project I’ve been thinking of was actually originally written for 1.6, which is the basic reason why all the custom work in that project was done in custom manager methods.)
The rationale behind doing this is explained in the 1.7 release notes.
If you create a Manager from a QuerySet class, it copies the methods of that class into the Manager, allowing those methods to be used on the Manager directly. (Note, this happens with all Managers, not just custom managers. Otherwise, you’d probably need to do something like MyModel.objects.all()
to get a queryset object that could later be filtered, annotated, etc. e.g., There wouldn’t be a filter()
method on objects
so MyModel.objects.filter()
would fail.)
The best that I can tell then, as far as queries and methods are concerned, yes, they are (now) functionally identical.
The differences then would be in the initialization and setup of these Managers with their associated models. Remember that in addition to any Managers defined by the developer, there are also implicit Managers that get created, including the _base_manager
and any “related managers”, so it’s probably unusual for there to be a model with only one manager.
The conclusion that I draw from this is that these are logically two different “things”, and the overlap comes from having the Manager copy the QuerySet methods into itself to allow those queryset methods to be used directly on the manager.
That also means that in the common case, I wouldn’t see a specific reason to create custom query methods on the Manager. (Other methods, those that don’t specifically work with querysets, could still be appropriately written in a manager.)