Model methods, Custom Managers & QuerySet - When to use them?

I was wondering how you organize your code.

How do you decide when the logic goes into a model method, a Custom Manager or QuerySet?

If possible, code snippets with examples would be much appreciated.

Thanks.

Typically, I use a model method if the logic works on an individual row. (e.g. A method that calculates a value based upon fields in the model.)

I use a Custom Manager when I have defaults to apply to querysets - it’s logic that applies to a collection of rows. (e.g. A model with an “active” flag, where every queryset for that model is supposed to check that that active flag is true.)

I don’t know what you mean by saying that the “logic goes into a queryset”.

1 Like

Hi Ken, thanks for your response.

About “logic goes into a queryset”. I was thinking something like this:

Source

class CourseQuerySet(models.QuerySet):
    def not_started(self):
        now = timezone.now()
        return self.filter(start__gt=now)

    def in_session(self):
        now = timezone.now()
        return self.filter(start__lte=now, end__gte=now)

    def ended(self):
        now = timezone.now()
        return self.filter(end__lt=now)

class CourseManager(models.Manager):
    def get_queryset(self):
        return CourseQuerySet(self.model, using=self._db)

    def not_started(self):
        return self.get_queryset().not_started()

    def in_session(self):
        return self.get_queryset().in_session()

    def ended(self):
        return self.get_queryset().ended()

The logic is implemented in CourseQuerySet. In articles I’ve read, it seems that when you do it this way, you can:

  • Chain methods, while if you do it in the CourseManager you can’t.
  • You can customize the get_queryset() to not get all objects.

Is this ok?
Are there other benefits in using CourseQuerySet?

Thanks.

Yes, now I understand what you’re referring to.

I don’t think we use them (custom querysets) at all. We have some complex conditions on some of our queries that are all encapsulated within manager methods, but they’re all logically atomic. I can’t think of any situation where we would want to break down those tests into smaller components, and even less likely to want to make them “composable” in queries by chaining them.

Obviously different people have different needs - and even different design patterns. Nothing I’m saying here is intended to imply that they’re not needed or useful. It’s just that they’re not useful to me, and so I don’t tend to think about them.

1 Like

Thanks for your insight Ken.
Let’s see what other people comment about it.

1 Like