~ubuntu-branches/debian/sid/python-django/sid

« back to all changes in this revision

Viewing changes to django/db/models/manager.py

  • Committer: Package Import Robot
  • Author(s): Raphaël Hertzog
  • Date: 2014-09-17 14:15:11 UTC
  • mfrom: (1.3.17) (6.2.18 experimental)
  • Revision ID: package-import@ubuntu.com-20140917141511-icneokthe9ww5sk4
Tags: 1.7-2
* Release to unstable.
* Add a migrate-south sample script to help users apply their South
  migrations. Thanks to Brian May.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
import copy
 
2
import inspect
 
3
 
2
4
from django.db import router
3
 
from django.db.models.query import QuerySet, insert_query, RawQuerySet
 
5
from django.db.models.query import QuerySet
4
6
from django.db.models import signals
5
7
from django.db.models.fields import FieldDoesNotExist
6
8
from django.utils import six
7
 
from django.utils.deprecation import RenameMethodsBase
 
9
from django.utils.deprecation import RenameMethodsBase, RemovedInDjango18Warning
 
10
from django.utils.encoding import python_2_unicode_compatible
 
11
 
8
12
 
9
13
def ensure_default_manager(sender, **kwargs):
10
14
    """
50
54
 
51
55
class RenameManagerMethods(RenameMethodsBase):
52
56
    renamed_methods = (
53
 
        ('get_query_set', 'get_queryset', PendingDeprecationWarning),
54
 
        ('get_prefetch_query_set', 'get_prefetch_queryset', PendingDeprecationWarning),
 
57
        ('get_query_set', 'get_queryset', RemovedInDjango18Warning),
 
58
        ('get_prefetch_query_set', 'get_prefetch_queryset', RemovedInDjango18Warning),
55
59
    )
56
60
 
57
61
 
58
 
class Manager(six.with_metaclass(RenameManagerMethods)):
 
62
@python_2_unicode_compatible
 
63
class BaseManager(six.with_metaclass(RenameManagerMethods)):
59
64
    # Tracks each time a Manager instance is created. Used to retain order.
60
65
    creation_counter = 0
61
66
 
62
67
    def __init__(self):
63
 
        super(Manager, self).__init__()
 
68
        super(BaseManager, self).__init__()
64
69
        self._set_creation_counter()
65
70
        self.model = None
66
71
        self._inherited = False
67
72
        self._db = None
 
73
        self._hints = {}
 
74
 
 
75
    def __str__(self):
 
76
        """ Return "app_label.model_label.manager_name". """
 
77
        model = self.model
 
78
        opts = model._meta
 
79
        app = model._meta.app_label
 
80
        manager_name = next(name for (_, name, manager)
 
81
            in opts.concrete_managers + opts.abstract_managers
 
82
            if manager == self)
 
83
        return '%s.%s.%s' % (app, model._meta.object_name, manager_name)
 
84
 
 
85
    def check(self, **kwargs):
 
86
        return []
 
87
 
 
88
    @classmethod
 
89
    def _get_queryset_methods(cls, queryset_class):
 
90
        def create_method(name, method):
 
91
            def manager_method(self, *args, **kwargs):
 
92
                return getattr(self.get_queryset(), name)(*args, **kwargs)
 
93
            manager_method.__name__ = method.__name__
 
94
            manager_method.__doc__ = method.__doc__
 
95
            return manager_method
 
96
 
 
97
        new_methods = {}
 
98
        # Refs http://bugs.python.org/issue1785.
 
99
        predicate = inspect.isfunction if six.PY3 else inspect.ismethod
 
100
        for name, method in inspect.getmembers(queryset_class, predicate=predicate):
 
101
            # Only copy missing methods.
 
102
            if hasattr(cls, name):
 
103
                continue
 
104
            # Only copy public methods or methods with the attribute `queryset_only=False`.
 
105
            queryset_only = getattr(method, 'queryset_only', None)
 
106
            if queryset_only or (queryset_only is None and name.startswith('_')):
 
107
                continue
 
108
            # Copy the method onto the manager.
 
109
            new_methods[name] = create_method(name, method)
 
110
        return new_methods
 
111
 
 
112
    @classmethod
 
113
    def from_queryset(cls, queryset_class, class_name=None):
 
114
        if class_name is None:
 
115
            class_name = '%sFrom%s' % (cls.__name__, queryset_class.__name__)
 
116
        class_dict = {
 
117
            '_queryset_class': queryset_class,
 
118
        }
 
119
        class_dict.update(cls._get_queryset_methods(queryset_class))
 
120
        return type(class_name, (cls,), class_dict)
68
121
 
69
122
    def contribute_to_class(self, model, name):
70
123
        # TODO: Use weakref because of possible memory leak / circular reference.
75
128
        elif model._meta.swapped:
76
129
            setattr(model, name, SwappedManagerDescriptor(model))
77
130
        else:
78
 
        # if not model._meta.abstract and not model._meta.swapped:
 
131
            # if not model._meta.abstract and not model._meta.swapped:
79
132
            setattr(model, name, ManagerDescriptor(self))
80
133
        if not getattr(model, '_default_manager', None) or self.creation_counter < model._default_manager.creation_counter:
81
134
            model._default_manager = self
91
144
        Sets the creation counter value for this instance and increments the
92
145
        class-level copy.
93
146
        """
94
 
        self.creation_counter = Manager.creation_counter
95
 
        Manager.creation_counter += 1
 
147
        self.creation_counter = BaseManager.creation_counter
 
148
        BaseManager.creation_counter += 1
96
149
 
97
150
    def _copy_to_model(self, model):
98
151
        """
107
160
        mgr._inherited = True
108
161
        return mgr
109
162
 
110
 
    def db_manager(self, using):
 
163
    def db_manager(self, using=None, hints=None):
111
164
        obj = copy.copy(self)
112
 
        obj._db = using
 
165
        obj._db = using or self._db
 
166
        obj._hints = hints or self._hints
113
167
        return obj
114
168
 
115
169
    @property
116
170
    def db(self):
117
 
        return self._db or router.db_for_read(self.model)
 
171
        return self._db or router.db_for_read(self.model, **self._hints)
118
172
 
119
173
    #######################
120
174
    # PROXIES TO QUERYSET #
121
175
    #######################
122
176
 
123
177
    def get_queryset(self):
124
 
        """Returns a new QuerySet object.  Subclasses can override this method
125
 
        to easily customize the behavior of the Manager.
126
 
        """
127
 
        return QuerySet(self.model, using=self._db)
128
 
 
129
 
    def none(self):
130
 
        return self.get_queryset().none()
 
178
        """
 
179
        Returns a new QuerySet object.  Subclasses can override this method to
 
180
        easily customize the behavior of the Manager.
 
181
        """
 
182
        return self._queryset_class(self.model, using=self._db, hints=self._hints)
131
183
 
132
184
    def all(self):
 
185
        # We can't proxy this method through the `QuerySet` like we do for the
 
186
        # rest of the `QuerySet` methods. This is because `QuerySet.all()`
 
187
        # works by creating a "copy" of the current queryset and in making said
 
188
        # copy, all the cached `prefetch_related` lookups are lost. See the
 
189
        # implementation of `RelatedManager.get_queryset()` for a better
 
190
        # understanding of how this comes into play.
133
191
        return self.get_queryset()
134
192
 
135
 
    def count(self):
136
 
        return self.get_queryset().count()
137
 
 
138
 
    def dates(self, *args, **kwargs):
139
 
        return self.get_queryset().dates(*args, **kwargs)
140
 
 
141
 
    def datetimes(self, *args, **kwargs):
142
 
        return self.get_queryset().datetimes(*args, **kwargs)
143
 
 
144
 
    def distinct(self, *args, **kwargs):
145
 
        return self.get_queryset().distinct(*args, **kwargs)
146
 
 
147
 
    def extra(self, *args, **kwargs):
148
 
        return self.get_queryset().extra(*args, **kwargs)
149
 
 
150
 
    def get(self, *args, **kwargs):
151
 
        return self.get_queryset().get(*args, **kwargs)
152
 
 
153
 
    def get_or_create(self, **kwargs):
154
 
        return self.get_queryset().get_or_create(**kwargs)
155
 
 
156
 
    def create(self, **kwargs):
157
 
        return self.get_queryset().create(**kwargs)
158
 
 
159
 
    def bulk_create(self, *args, **kwargs):
160
 
        return self.get_queryset().bulk_create(*args, **kwargs)
161
 
 
162
 
    def filter(self, *args, **kwargs):
163
 
        return self.get_queryset().filter(*args, **kwargs)
164
 
 
165
 
    def aggregate(self, *args, **kwargs):
166
 
        return self.get_queryset().aggregate(*args, **kwargs)
167
 
 
168
 
    def annotate(self, *args, **kwargs):
169
 
        return self.get_queryset().annotate(*args, **kwargs)
170
 
 
171
 
    def complex_filter(self, *args, **kwargs):
172
 
        return self.get_queryset().complex_filter(*args, **kwargs)
173
 
 
174
 
    def exclude(self, *args, **kwargs):
175
 
        return self.get_queryset().exclude(*args, **kwargs)
176
 
 
177
 
    def in_bulk(self, *args, **kwargs):
178
 
        return self.get_queryset().in_bulk(*args, **kwargs)
179
 
 
180
 
    def iterator(self, *args, **kwargs):
181
 
        return self.get_queryset().iterator(*args, **kwargs)
182
 
 
183
 
    def earliest(self, *args, **kwargs):
184
 
        return self.get_queryset().earliest(*args, **kwargs)
185
 
 
186
 
    def latest(self, *args, **kwargs):
187
 
        return self.get_queryset().latest(*args, **kwargs)
188
 
 
189
 
    def first(self):
190
 
        return self.get_queryset().first()
191
 
 
192
 
    def last(self):
193
 
        return self.get_queryset().last()
194
 
 
195
 
    def order_by(self, *args, **kwargs):
196
 
        return self.get_queryset().order_by(*args, **kwargs)
197
 
 
198
 
    def select_for_update(self, *args, **kwargs):
199
 
        return self.get_queryset().select_for_update(*args, **kwargs)
200
 
 
201
 
    def select_related(self, *args, **kwargs):
202
 
        return self.get_queryset().select_related(*args, **kwargs)
203
 
 
204
 
    def prefetch_related(self, *args, **kwargs):
205
 
        return self.get_queryset().prefetch_related(*args, **kwargs)
206
 
 
207
 
    def values(self, *args, **kwargs):
208
 
        return self.get_queryset().values(*args, **kwargs)
209
 
 
210
 
    def values_list(self, *args, **kwargs):
211
 
        return self.get_queryset().values_list(*args, **kwargs)
212
 
 
213
 
    def update(self, *args, **kwargs):
214
 
        return self.get_queryset().update(*args, **kwargs)
215
 
 
216
 
    def reverse(self, *args, **kwargs):
217
 
        return self.get_queryset().reverse(*args, **kwargs)
218
 
 
219
 
    def defer(self, *args, **kwargs):
220
 
        return self.get_queryset().defer(*args, **kwargs)
221
 
 
222
 
    def only(self, *args, **kwargs):
223
 
        return self.get_queryset().only(*args, **kwargs)
224
 
 
225
 
    def using(self, *args, **kwargs):
226
 
        return self.get_queryset().using(*args, **kwargs)
227
 
 
228
 
    def exists(self, *args, **kwargs):
229
 
        return self.get_queryset().exists(*args, **kwargs)
230
 
 
231
 
    def _insert(self, objs, fields, **kwargs):
232
 
        return insert_query(self.model, objs, fields, **kwargs)
233
 
 
234
 
    def _update(self, values, **kwargs):
235
 
        return self.get_queryset()._update(values, **kwargs)
236
 
 
237
 
    def raw(self, raw_query, params=None, *args, **kwargs):
238
 
        return RawQuerySet(raw_query=raw_query, model=self.model, params=params, using=self._db, *args, **kwargs)
 
193
 
 
194
class Manager(BaseManager.from_queryset(QuerySet)):
 
195
    pass
239
196
 
240
197
 
241
198
class ManagerDescriptor(object):
245
202
        self.manager = manager
246
203
 
247
204
    def __get__(self, instance, type=None):
248
 
        if instance != None:
 
205
        if instance is not None:
249
206
            raise AttributeError("Manager isn't accessible via %s instances" % type.__name__)
250
207
        return self.manager
251
208