Managers | Adding extra manager method VS Creating a manager with QuerySet methods

Hi,
What is the difference between Adding an extra manager method, and assign the new manager to the ‘objects’ attribute:

class PollManager(models.Manager):
def with_counts(self):
return self.annotate(
num_responses=Coalesce(models.Count(“response”), 0)
)
class OpinionPoll(models.Model):

objects = PollManager()

…Versus Creating a manager with QuerySet methods (using as_manager) ?

class Person(models.Model):

people = PersonQuerySet.as_manager()

The difference of using "from_queryset’ is pretty obvious, as it allows a modularity…

P.S
Best practices to use Managers will be welcomed and also advices for Junior Devs that are new to Django…
Thanks !

1 Like

Hi LiorA1,

The examples you copied from the documentation aren’t direct comparisons. If you look at the start of this section of the docs, it attempts to explain that using .as_manager allows you to define methods for both the manager and the queryset avoiding some duplication.

class PersonQuerySet(models.QuerySet):
    def authors(self):
        return self.filter(role='A')

    def editors(self):
        return self.filter(role='E')

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

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

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

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    role = models.CharField(max_length=1, choices=[('A', _('Author')), ('E', _('Editor'))])
    people = PersonManager()

Can be reduced and defined as such:

class PersonQuerySet(models.QuerySet):
    def authors(self):
        return self.filter(role='A')

    def editors(self):
        return self.filter(role='E')


class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    role = models.CharField(max_length=1, choices=[('A', _('Author')), ('E', _('Editor'))])
    people = PersonQuerySet.as_manager()

I hope that helps to clear up the issue a bit. If it doesn’t, please let me/us know.

-Tim

2 Likes

Yeah its what I thought.

I just wondered why one will use the custom QuerySet with ‘as_manager’ and not a direct custom Manager…

Thanks !

I’m sure there’s a use case out there, but I haven’t encountered it yet. Perhaps someone a bit more versed in Django’s history here can chime in. However it does look like these queryset based approaches were introduced in 1.7. Or maybe the manager stuff is hanging around because it’s hard to deprecate and remove things? Especially when it doesn’t cause any immediate problems with the framework.

1 Like