| 1 | from types import MethodType
|
|---|
| 2 | from django.db import models
|
|---|
| 3 | from django.db.models.query import QuerySet
|
|---|
| 4 | from django.db.models.query import EmptyQuerySet
|
|---|
| 5 |
|
|---|
| 6 | class ManagerQuerySetDecorator(models.Manager):
|
|---|
| 7 | """
|
|---|
| 8 | Extends the operation methods of the manager on subqueries QuerySet objects.
|
|---|
| 9 |
|
|---|
| 10 | How to use:
|
|---|
| 11 |
|
|---|
| 12 | class ManagerQuerySet(models.query.QuerySet):
|
|---|
| 13 | def get_fun_people(self):
|
|---|
| 14 | return self.filter(fun=True)
|
|---|
| 15 |
|
|---|
| 16 | def get_not_fun_people(self):
|
|---|
| 17 | return self.filter(fun=False)
|
|---|
| 18 |
|
|---|
| 19 | class PersonManager(models.Manager):
|
|---|
| 20 | def __init__(self):
|
|---|
| 21 | super(PersonManager, self).__init__()
|
|---|
| 22 | self.implement_queryset_cls(ManagerQuerySet)
|
|---|
| 23 | self.implement_queryset_methods('get_fun_people', 'get_not_fun_people')
|
|---|
| 24 |
|
|---|
| 25 | class Person(models.Model):
|
|---|
| 26 | first_name = models.CharField(max_length=30)
|
|---|
| 27 | last_name = models.CharField(max_length=30)
|
|---|
| 28 | fun = models.BooleanField()
|
|---|
| 29 | objects = PersonManager()
|
|---|
| 30 | objects_second = PersonManagerSecond(ManagerQuerySet, ['get_fun_people', 'get_not_fun_people'])
|
|---|
| 31 |
|
|---|
| 32 | def __unicode__(self):
|
|---|
| 33 | return u"%s %s" % (self.first_name, self.last_name)
|
|---|
| 34 |
|
|---|
| 35 | # This works without a decorator
|
|---|
| 36 | Person.objects.get_fun_people().filter(firstname='John')
|
|---|
| 37 |
|
|---|
| 38 | # The decorator also provides such a possibility, which does not work currently in django.
|
|---|
| 39 | Person.objects.filter(firstname='John').get_fun_people()
|
|---|
| 40 | """
|
|---|
| 41 | def __init__(self, queryset_cls=None, queryset_method_names=[]):
|
|---|
| 42 | super(ManagerQuerySetDecorator, self).__init__()
|
|---|
| 43 | self._queryset_cls = queryset_cls or QuerySet
|
|---|
| 44 | self.implement_queryset_methods(*queryset_method_names)
|
|---|
| 45 |
|
|---|
| 46 | def implement_queryset_cls(self, cls):
|
|---|
| 47 | self._queryset_cls = cls
|
|---|
| 48 |
|
|---|
| 49 | def implement_queryset_methods(self, *method_names):
|
|---|
| 50 | for method_name in method_names:
|
|---|
| 51 | self.implement_queryset_method(method_name)
|
|---|
| 52 |
|
|---|
| 53 | def implement_queryset_method(self, name):
|
|---|
| 54 | def queryset_method_deco(*args, **kwarg):
|
|---|
| 55 | return getattr(self.get_query_set(), name)(*args, **kwarg)
|
|---|
| 56 | setattr(self, name, queryset_method_deco)
|
|---|
| 57 |
|
|---|
| 58 | def get_empty_query_set(self):
|
|---|
| 59 | return self._queryset_cls(self.model, using=self._db).none()
|
|---|
| 60 |
|
|---|
| 61 | def get_query_set(self):
|
|---|
| 62 | return self._queryset_cls(self.model, using=self._db)
|
|---|
| 63 |
|
|---|
| 64 |
|
|---|