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 | |
---|