The Django docs show us how to give models a custom manager. Unfortunately, filter methods defined this way cannot be chained to each other or to standard queryset filters. Try it:
class NewsManager(models.Manager): def live(self): return self.filter(state='published') def interesting(self): return self.filter(interesting=True) >>> NewsManager().live().interesting() AttributeError: '_QuerySet' object has no attribute 'interesting'
So, instead of adding our new filters to the custom manager, we add them to a custom queryset. But we still want to be able to access them as methods of the manager. We could add stub methods on the manager for each new filter, calling the corresponding method on the queryset - but that would be a blatant DRY violation. A custom
__getattr__ method on the manager takes care of that problem.
And now we can do:
>>> NewsManager().live().interesting() [<NewsItem: ...>]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
from django.db import models class NewsQuerySet(models.query.QuerySet): def live(self): return self.filter(state='published') def interesting(self): return self.filter(interesting=True) class NewsManager(models.Manager): def get_query_set(self): model = models.get_model('news', 'NewsItem') return NewsQuerySet(model) def __getattr__(self, attr, *args): try: return getattr(self.__class__, attr, *args) except AttributeError: return getattr(self.get_query_set(), attr, *args)
More like this
- Serializer factory with Django Rest Framework by julio 5 months, 3 weeks ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 6 months, 1 week ago
- Help text hyperlinks by sa2812 7 months ago
- Stuff by NixonDash 9 months, 1 week ago
- Add custom fields to the built-in Group model by jmoppel 11 months, 2 weeks ago