web/lib/django/db/models/query_utils.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
     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