Ticket #17270: manager.5.py

File manager.5.py, 2.3 KB (added by Wojciech Banaś <fizista@…>, 4 years ago)

Another solution, tested, working, downwards compatible, decorator

Line 
1from types import MethodType
2from django.db import models
3from django.db.models.query import QuerySet
4from django.db.models.query import EmptyQuerySet
5
6class 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   
Back to Top