0

Reading djangodocs about managers, I'm interested in different implementation of custom QuerySet methods.

So, I'm giving my examples. First implementations as in djangodocs:

class ProductQuerySet(models.QuerySet):
    def small(self):
        return self.filter(volume__lt=1)

    def large(self):
        return self.filter(volume__gt=4)

and then in model:

 objects = ProductQuerySet.as_manager()

Second simple implementation:

class VolumeManager(models.Manager):
    def small(self):
        return self.filter(volume__lt=1)

    def large(self):
        return self.filter(volume__gt=4)

and in model:

objects = VolumeManager()

Is there any difference between them? Or is there any special use of first implementation? I think that second implementation is easier and clear.

litwisha
  • 392
  • 3
  • 12

1 Answers1

3

Your second implementation is not chainable, by which I mean you cannot go Volume.objects.small().large(). I understand in your example this makes no sense, but in many implementations you want to chain custom filter methods.

You can do this with the first example where you are using the queryset as a manager. Before 'as_manager' was added, you had to duplicate the methods in both the manager and the queryset to make them chainable, like so:

class ProductMixin(object):
    def small(self):
        return self.filter(volume__lt=1)

    def large(self):
        return self.filter(volume__gt=4)

class ProductQuerySet(QuerySet, ProductMixin):
    pass

class ProductManager(models.Manager, ProductMixin):
    def get_query_set(self):
        return ProductQuerySet(self.model, using=self._db)

As you can see, the 'as_manager' method is a nice shortcut to avoid this sort of code duplication and verbosity. I believe it was inspired by the PassThroughManager which provided similar functionality

Mark Galloway
  • 4,050
  • 19
  • 26