1 import copy |
1 import copy |
2 |
2 |
3 from django.db.models.query import QuerySet, EmptyQuerySet, insert_query |
3 from django.db.models.query import QuerySet, EmptyQuerySet, insert_query |
4 from django.dispatch import dispatcher |
|
5 from django.db.models import signals |
4 from django.db.models import signals |
6 from django.db.models.fields import FieldDoesNotExist |
5 from django.db.models.fields import FieldDoesNotExist |
7 |
6 |
8 def ensure_default_manager(sender): |
7 def ensure_default_manager(sender, **kwargs): |
9 cls = sender |
8 cls = sender |
10 if not getattr(cls, '_default_manager', None) and not cls._meta.abstract: |
9 if not getattr(cls, '_default_manager', None) and not cls._meta.abstract: |
11 # Create the default manager, if needed. |
10 # Create the default manager, if needed. |
12 try: |
11 try: |
13 cls._meta.get_field('objects') |
12 cls._meta.get_field('objects') |
14 raise ValueError, "Model %s must specify a custom Manager, because it has a field named 'objects'" % cls.__name__ |
13 raise ValueError, "Model %s must specify a custom Manager, because it has a field named 'objects'" % cls.__name__ |
15 except FieldDoesNotExist: |
14 except FieldDoesNotExist: |
16 pass |
15 pass |
17 cls.add_to_class('objects', Manager()) |
16 cls.add_to_class('objects', Manager()) |
18 |
17 |
19 dispatcher.connect(ensure_default_manager, signal=signals.class_prepared) |
18 signals.class_prepared.connect(ensure_default_manager) |
20 |
19 |
21 class Manager(object): |
20 class Manager(object): |
22 # Tracks each time a Manager instance is created. Used to retain order. |
21 # Tracks each time a Manager instance is created. Used to retain order. |
23 creation_counter = 0 |
22 creation_counter = 0 |
24 |
23 |
25 def __init__(self): |
24 def __init__(self): |
26 super(Manager, self).__init__() |
25 super(Manager, self).__init__() |
27 # Increase the creation counter, and save our local copy. |
26 self._set_creation_counter() |
28 self.creation_counter = Manager.creation_counter |
|
29 Manager.creation_counter += 1 |
|
30 self.model = None |
27 self.model = None |
|
28 self._inherited = False |
31 |
29 |
32 def contribute_to_class(self, model, name): |
30 def contribute_to_class(self, model, name): |
33 # TODO: Use weakref because of possible memory leak / circular reference. |
31 # TODO: Use weakref because of possible memory leak / circular reference. |
34 self.model = model |
32 self.model = model |
35 setattr(model, name, ManagerDescriptor(self)) |
33 setattr(model, name, ManagerDescriptor(self)) |
36 if not getattr(model, '_default_manager', None) or self.creation_counter < model._default_manager.creation_counter: |
34 if not getattr(model, '_default_manager', None) or self.creation_counter < model._default_manager.creation_counter: |
37 model._default_manager = self |
35 model._default_manager = self |
|
36 if model._meta.abstract or self._inherited: |
|
37 model._meta.abstract_managers.append((self.creation_counter, name, |
|
38 self)) |
|
39 |
|
40 def _set_creation_counter(self): |
|
41 """ |
|
42 Sets the creation counter value for this instance and increments the |
|
43 class-level copy. |
|
44 """ |
|
45 self.creation_counter = Manager.creation_counter |
|
46 Manager.creation_counter += 1 |
38 |
47 |
39 def _copy_to_model(self, model): |
48 def _copy_to_model(self, model): |
40 """ |
49 """ |
41 Makes a copy of the manager and assigns it to 'model', which should be |
50 Makes a copy of the manager and assigns it to 'model', which should be |
42 a child of the existing model (used when inheriting a manager from an |
51 a child of the existing model (used when inheriting a manager from an |
43 abstract base class). |
52 abstract base class). |
44 """ |
53 """ |
45 assert issubclass(model, self.model) |
54 assert issubclass(model, self.model) |
46 mgr = copy.copy(self) |
55 mgr = copy.copy(self) |
|
56 mgr._set_creation_counter() |
47 mgr.model = model |
57 mgr.model = model |
|
58 mgr._inherited = True |
48 return mgr |
59 return mgr |
49 |
60 |
50 ####################### |
61 ####################### |
51 # PROXIES TO QUERYSET # |
62 # PROXIES TO QUERYSET # |
52 ####################### |
63 ####################### |