2 Various data structures used in query construction.
4 Factored out from django.db.models.query to avoid making the main module very
5 large and/or so that they can be used by other modules without getting into
6 circular import difficulties.
11 from django
.db
.backends
import util
12 from django
.utils
import tree
15 class InvalidQuery(Exception):
17 The query passed to raw isn't a safe query to use with raw.
22 class QueryWrapper(object):
24 A type that indicates the contents are an SQL fragment and the associate
25 parameters. Can be used to pass opaque data to a where-clause, for example.
27 def __init__(self
, sql
, params
):
28 self
.data
= sql
, params
30 def as_sql(self
, qn
=None, connection
=None):
35 Encapsulates filters as objects that can then be combined logically (using
43 def __init__(self
, *args
, **kwargs
):
44 super(Q
, self
).__init
__(children
=list(args
) + kwargs
.items())
46 def _combine(self
, other
, conn
):
47 if not isinstance(other
, Q
):
48 raise TypeError(other
)
54 def __or__(self
, other
):
55 return self
._combine
(other
, self
.OR
)
57 def __and__(self
, other
):
58 return self
._combine
(other
, self
.AND
)
62 obj
.add(self
, self
.AND
)
66 class DeferredAttribute(object):
68 A wrapper for a deferred-loading field. When the value is read from this
69 object the first time, the query is executed.
71 def __init__(self
, field_name
, model
):
72 self
.field_name
= field_name
73 self
.model_ref
= weakref
.ref(model
)
76 def __get__(self
, instance
, owner
):
78 Retrieves and caches the value from the datastore on the first lookup.
79 Returns the cached value.
81 from django
.db
.models
.fields
import FieldDoesNotExist
83 assert instance
is not None
84 cls
= self
.model_ref()
85 data
= instance
.__dict
__
86 if data
.get(self
.field_name
, self
) is self
:
87 # self.field_name is the attname of the field, but only() takes the
88 # actual name, so we need to translate it here.
90 cls
._meta
.get_field_by_name(self
.field_name
)
91 name
= self
.field_name
92 except FieldDoesNotExist
:
93 name
= [f
.name
for f
in cls
._meta
.fields
94 if f
.attname
== self
.field_name
][0]
95 # We use only() instead of values() here because we want the
96 # various data coersion methods (to_python(), etc.) to be called
99 cls
._base
_manager
.filter(pk
=instance
.pk
).only(name
).using(
100 instance
._state
.db
).get(),
103 data
[self
.field_name
] = val
104 return data
[self
.field_name
]
106 def __set__(self
, instance
, value
):
108 Deferred loading attributes can be set normally (which means there will
109 never be a database lookup involved.
111 instance
.__dict
__[self
.field_name
] = value
113 def select_related_descend(field
, restricted
, requested
, reverse
=False):
115 Returns True if this field should be used to descend deeper for
116 select_related() purposes. Used by both the query construction code
117 (sql.query.fill_related_selections()) and the model instance creation code
118 (query.get_cached_row()).
121 * field - the field to be checked
122 * restricted - a boolean field, indicating if the field list has been
123 manually restricted using a requested clause)
124 * requested - The select_related() dictionary.
125 * reverse - boolean, True if we are checking a reverse select related
129 if field
.rel
.parent_link
and not reverse
:
132 if reverse
and field
.related_query_name() not in requested
:
134 if not reverse
and field
.name
not in requested
:
136 if not restricted
and field
.null
:
140 # This function is needed because data descriptors must be defined on a class
141 # object, not an instance, to have any effect.
143 def deferred_class_factory(model
, attrs
):
145 Returns a class object that is a copy of "model" with the specified "attrs"
146 being replaced with DeferredAttribute objects. The "pk_value" ties the
147 deferred attributes to a particular instance of the model.
151 app_label
= model
._meta
.app_label
153 # The app_cache wants a unique name for each model, otherwise the new class
154 # won't be created (we get an old one back). Therefore, we generate the
155 # name using the passed in attrs. It's OK to reuse an existing class
156 # object if the attrs are identical.
157 name
= "%s_Deferred_%s" % (model
.__name
__, '_'.join(sorted(list(attrs
))))
158 name
= util
.truncate_name(name
, 80, 32)
160 overrides
= dict([(attr
, DeferredAttribute(attr
, model
))
162 overrides
["Meta"] = Meta
163 overrides
["__module__"] = model
.__module
__
164 overrides
["_deferred"] = True
165 return type(name
, (model
,), overrides
)
167 # The above function is also used to unpickle model instances with deferred
169 deferred_class_factory
.__safe
_for
_unpickling
__ = True