App Engine Python SDK version 1.7.4 (2)
[gae.git] / python / lib / django_1_4 / django / db / models / query_utils.py
bloba56ab5ca80d6f07a3c70bab3390851b4a6a629aa
1 """
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.
7 """
9 import weakref
11 from django.db.backends import util
12 from django.utils import tree
15 class InvalidQuery(Exception):
16 """
17 The query passed to raw isn't a safe query to use with raw.
18 """
19 pass
22 class QueryWrapper(object):
23 """
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.
26 """
27 def __init__(self, sql, params):
28 self.data = sql, params
30 def as_sql(self, qn=None, connection=None):
31 return self.data
33 class Q(tree.Node):
34 """
35 Encapsulates filters as objects that can then be combined logically (using
36 & and |).
37 """
38 # Connection types
39 AND = 'AND'
40 OR = 'OR'
41 default = AND
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)
49 obj = type(self)()
50 obj.add(self, conn)
51 obj.add(other, conn)
52 return obj
54 def __or__(self, other):
55 return self._combine(other, self.OR)
57 def __and__(self, other):
58 return self._combine(other, self.AND)
60 def __invert__(self):
61 obj = type(self)()
62 obj.add(self, self.AND)
63 obj.negate()
64 return obj
66 class DeferredAttribute(object):
67 """
68 A wrapper for a deferred-loading field. When the value is read from this
69 object the first time, the query is executed.
70 """
71 def __init__(self, field_name, model):
72 self.field_name = field_name
73 self.model_ref = weakref.ref(model)
74 self.loaded = False
76 def __get__(self, instance, owner):
77 """
78 Retrieves and caches the value from the datastore on the first lookup.
79 Returns the cached value.
80 """
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.
89 try:
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
97 # here.
98 val = getattr(
99 cls._base_manager.filter(pk=instance.pk).only(name).using(
100 instance._state.db).get(),
101 self.field_name
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()).
120 Arguments:
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
127 if not field.rel:
128 return False
129 if field.rel.parent_link and not reverse:
130 return False
131 if restricted:
132 if reverse and field.related_query_name() not in requested:
133 return False
134 if not reverse and field.name not in requested:
135 return False
136 if not restricted and field.null:
137 return False
138 return True
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.
149 class Meta:
150 proxy = True
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))
161 for attr in attrs])
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
168 # fields.
169 deferred_class_factory.__safe_for_unpickling__ = True