5 large and/or so that they can be used by other modules without getting into |
5 large and/or so that they can be used by other modules without getting into |
6 circular import difficulties. |
6 circular import difficulties. |
7 """ |
7 """ |
8 |
8 |
9 import weakref |
9 import weakref |
10 from copy import deepcopy |
10 from django.utils.copycompat import deepcopy |
11 |
11 |
12 from django.utils import tree |
12 from django.utils import tree |
13 from django.utils.datastructures import SortedDict |
13 from django.utils.datastructures import SortedDict |
14 |
14 |
15 try: |
|
16 sorted |
|
17 except NameError: |
|
18 from django.utils.itercompat import sorted # For Python 2.3. |
|
19 |
|
20 |
15 |
21 class CyclicDependency(Exception): |
16 class CyclicDependency(Exception): |
22 """ |
17 """ |
23 An error when dealing with a collection of objects that have a cyclic |
18 An error when dealing with a collection of objects that have a cyclic |
24 dependency, i.e. when deleting multiple objects. |
19 dependency, i.e. when deleting multiple objects. |
25 """ |
20 """ |
26 pass |
21 pass |
|
22 |
|
23 class InvalidQuery(Exception): |
|
24 """ |
|
25 The query passed to raw isn't a safe query to use with raw. |
|
26 """ |
|
27 pass |
|
28 |
27 |
29 |
28 class CollectedObjects(object): |
30 class CollectedObjects(object): |
29 """ |
31 """ |
30 A container that stores keys and lists of values along with remembering the |
32 A container that stores keys and lists of values along with remembering the |
31 parent objects for all the keys. |
33 parent objects for all the keys. |
46 for cls, seen in previously_seen.data.items(): |
48 for cls, seen in previously_seen.data.items(): |
47 self.blocked.setdefault(cls, SortedDict()).update(seen) |
49 self.blocked.setdefault(cls, SortedDict()).update(seen) |
48 else: |
50 else: |
49 self.blocked = {} |
51 self.blocked = {} |
50 |
52 |
51 def add(self, model, pk, obj, parent_model, nullable=False): |
53 def add(self, model, pk, obj, parent_model, parent_obj=None, nullable=False): |
52 """ |
54 """ |
53 Adds an item to the container. |
55 Adds an item to the container. |
54 |
56 |
55 Arguments: |
57 Arguments: |
56 * model - the class of the object being added. |
58 * model - the class of the object being added. |
57 * pk - the primary key. |
59 * pk - the primary key. |
58 * obj - the object itself. |
60 * obj - the object itself. |
59 * parent_model - the model of the parent object that this object was |
61 * parent_model - the model of the parent object that this object was |
60 reached through. |
62 reached through. |
|
63 * parent_obj - the parent object this object was reached |
|
64 through (not used here, but needed in the API for use elsewhere) |
61 * nullable - should be True if this relation is nullable. |
65 * nullable - should be True if this relation is nullable. |
62 |
66 |
63 Returns True if the item already existed in the structure and |
67 Returns True if the item already existed in the structure and |
64 False otherwise. |
68 False otherwise. |
65 """ |
69 """ |
130 parameters. Can be used to pass opaque data to a where-clause, for example. |
134 parameters. Can be used to pass opaque data to a where-clause, for example. |
131 """ |
135 """ |
132 def __init__(self, sql, params): |
136 def __init__(self, sql, params): |
133 self.data = sql, params |
137 self.data = sql, params |
134 |
138 |
135 def as_sql(self, qn=None): |
139 def as_sql(self, qn=None, connection=None): |
136 return self.data |
140 return self.data |
137 |
141 |
138 class Q(tree.Node): |
142 class Q(tree.Node): |
139 """ |
143 """ |
140 Encapsulates filters as objects that can then be combined logically (using |
144 Encapsulates filters as objects that can then be combined logically (using |
149 super(Q, self).__init__(children=list(args) + kwargs.items()) |
153 super(Q, self).__init__(children=list(args) + kwargs.items()) |
150 |
154 |
151 def _combine(self, other, conn): |
155 def _combine(self, other, conn): |
152 if not isinstance(other, Q): |
156 if not isinstance(other, Q): |
153 raise TypeError(other) |
157 raise TypeError(other) |
154 obj = deepcopy(self) |
158 obj = type(self)() |
|
159 obj.add(self, conn) |
155 obj.add(other, conn) |
160 obj.add(other, conn) |
156 return obj |
161 return obj |
157 |
162 |
158 def __or__(self, other): |
163 def __or__(self, other): |
159 return self._combine(other, self.OR) |
164 return self._combine(other, self.OR) |
160 |
165 |
161 def __and__(self, other): |
166 def __and__(self, other): |
162 return self._combine(other, self.AND) |
167 return self._combine(other, self.AND) |
163 |
168 |
164 def __invert__(self): |
169 def __invert__(self): |
165 obj = deepcopy(self) |
170 obj = type(self)() |
|
171 obj.add(self, self.AND) |
166 obj.negate() |
172 obj.negate() |
167 return obj |
173 return obj |
168 |
174 |
169 class DeferredAttribute(object): |
175 class DeferredAttribute(object): |
170 """ |
176 """ |
179 def __get__(self, instance, owner): |
185 def __get__(self, instance, owner): |
180 """ |
186 """ |
181 Retrieves and caches the value from the datastore on the first lookup. |
187 Retrieves and caches the value from the datastore on the first lookup. |
182 Returns the cached value. |
188 Returns the cached value. |
183 """ |
189 """ |
|
190 from django.db.models.fields import FieldDoesNotExist |
|
191 |
184 assert instance is not None |
192 assert instance is not None |
185 cls = self.model_ref() |
193 cls = self.model_ref() |
186 data = instance.__dict__ |
194 data = instance.__dict__ |
187 if data.get(self.field_name, self) is self: |
195 if data.get(self.field_name, self) is self: |
188 data[self.field_name] = cls._base_manager.filter(pk=instance.pk).values_list(self.field_name, flat=True).get() |
196 # self.field_name is the attname of the field, but only() takes the |
|
197 # actual name, so we need to translate it here. |
|
198 try: |
|
199 cls._meta.get_field_by_name(self.field_name) |
|
200 name = self.field_name |
|
201 except FieldDoesNotExist: |
|
202 name = [f.name for f in cls._meta.fields |
|
203 if f.attname == self.field_name][0] |
|
204 # We use only() instead of values() here because we want the |
|
205 # various data coersion methods (to_python(), etc.) to be called |
|
206 # here. |
|
207 val = getattr( |
|
208 cls._base_manager.filter(pk=instance.pk).only(name).using( |
|
209 instance._state.db).get(), |
|
210 self.field_name |
|
211 ) |
|
212 data[self.field_name] = val |
189 return data[self.field_name] |
213 return data[self.field_name] |
190 |
214 |
191 def __set__(self, instance, value): |
215 def __set__(self, instance, value): |
192 """ |
216 """ |
193 Deferred loading attributes can be set normally (which means there will |
217 Deferred loading attributes can be set normally (which means there will |
194 never be a database lookup involved. |
218 never be a database lookup involved. |
195 """ |
219 """ |
196 instance.__dict__[self.field_name] = value |
220 instance.__dict__[self.field_name] = value |
197 |
221 |
198 def select_related_descend(field, restricted, requested): |
222 def select_related_descend(field, restricted, requested, reverse=False): |
199 """ |
223 """ |
200 Returns True if this field should be used to descend deeper for |
224 Returns True if this field should be used to descend deeper for |
201 select_related() purposes. Used by both the query construction code |
225 select_related() purposes. Used by both the query construction code |
202 (sql.query.fill_related_selections()) and the model instance creation code |
226 (sql.query.fill_related_selections()) and the model instance creation code |
203 (query.get_cached_row()). |
227 (query.get_cached_row()). |
|
228 |
|
229 Arguments: |
|
230 * field - the field to be checked |
|
231 * restricted - a boolean field, indicating if the field list has been |
|
232 manually restricted using a requested clause) |
|
233 * requested - The select_related() dictionary. |
|
234 * reverse - boolean, True if we are checking a reverse select related |
204 """ |
235 """ |
205 if not field.rel: |
236 if not field.rel: |
206 return False |
237 return False |
207 if field.rel.parent_link: |
238 if field.rel.parent_link and not reverse: |
208 return False |
239 return False |
209 if restricted and field.name not in requested: |
240 if restricted: |
210 return False |
241 if reverse and field.related_query_name() not in requested: |
|
242 return False |
|
243 if not reverse and field.name not in requested: |
|
244 return False |
211 if not restricted and field.null: |
245 if not restricted and field.null: |
212 return False |
246 return False |
213 return True |
247 return True |
214 |
248 |
215 # This function is needed because data descriptors must be defined on a class |
249 # This function is needed because data descriptors must be defined on a class |