Reading through some common Django books and tutorials, you will come upon the advice to encapsulate your ORM-related business logic inside custom model managers and custom querysets.

In this article, I will try to persuade you no to. Or at the very least, to persuade you that the bar should be very high for introducing those constructs.

What are custom managers / querysets?

TODO

The stated benefits:

  • DRY principle
  • High level logic is clear
  • Codifies field semantics of a model – you can see how to interpret certain fields

My beef with them

Beef #1: Mixed semantics

If you app grows beyond the starting phase, you model will certainly be used in multiple apps. E.g. if you have a content taxonomy model, it might be used for recommending similar content, and it might be used for determining user’s interests.

Beef #2: Now I have to learn your custom DSL

In a Django project, Django’s ORM is the common language between developers. By introducing custom manager methods, now you’re forcing me to use them instead of the ORM. Now I can no longer glance at the function and see all queries. Instead, I have to jump around the file(s) trying to piece together what’s going on.

Beef #3: Nobody knows about them

Use cases come and go. Unless you’re the sole developer on the project, you can’t keep up with the influx of helper methods on the model. Even you might forget about them. If the project is even of medium size, no one can keep up with the influx of helper methods on the custom manager.

What to do instead?

There is a place for the custom manager methods, but the bar for promoting a functionality there has to be extremely high. The criteria are:

  1. very important to get it right
  2. complex
  3. used all over the place

If your functionality doesn’t meet all of these criteria, it would probably be better for it to live in the app’s utils.py, the service layer or on the model itself.