web/lib/django/db/models/fields/related.py
changeset 0 0d40e90630ef
child 29 cc9b7e14412b
equal deleted inserted replaced
-1:000000000000 0:0d40e90630ef
       
     1 from django.db import connection, transaction
       
     2 from django.db.backends import util
       
     3 from django.db.models import signals, get_model
       
     4 from django.db.models.fields import AutoField, Field, IntegerField, PositiveIntegerField, PositiveSmallIntegerField, FieldDoesNotExist
       
     5 from django.db.models.related import RelatedObject
       
     6 from django.db.models.query import QuerySet
       
     7 from django.db.models.query_utils import QueryWrapper
       
     8 from django.utils.encoding import smart_unicode
       
     9 from django.utils.translation import ugettext_lazy, string_concat, ungettext, ugettext as _
       
    10 from django.utils.functional import curry
       
    11 from django.core import exceptions
       
    12 from django import forms
       
    13 
       
    14 try:
       
    15     set
       
    16 except NameError:
       
    17     from sets import Set as set   # Python 2.3 fallback
       
    18 
       
    19 RECURSIVE_RELATIONSHIP_CONSTANT = 'self'
       
    20 
       
    21 pending_lookups = {}
       
    22 
       
    23 def add_lazy_relation(cls, field, relation, operation):
       
    24     """
       
    25     Adds a lookup on ``cls`` when a related field is defined using a string,
       
    26     i.e.::
       
    27 
       
    28         class MyModel(Model):
       
    29             fk = ForeignKey("AnotherModel")
       
    30 
       
    31     This string can be:
       
    32 
       
    33         * RECURSIVE_RELATIONSHIP_CONSTANT (i.e. "self") to indicate a recursive
       
    34           relation.
       
    35 
       
    36         * The name of a model (i.e "AnotherModel") to indicate another model in
       
    37           the same app.
       
    38 
       
    39         * An app-label and model name (i.e. "someapp.AnotherModel") to indicate
       
    40           another model in a different app.
       
    41 
       
    42     If the other model hasn't yet been loaded -- almost a given if you're using
       
    43     lazy relationships -- then the relation won't be set up until the
       
    44     class_prepared signal fires at the end of model initialization.
       
    45 
       
    46     operation is the work that must be performed once the relation can be resolved.
       
    47     """
       
    48     # Check for recursive relations
       
    49     if relation == RECURSIVE_RELATIONSHIP_CONSTANT:
       
    50         app_label = cls._meta.app_label
       
    51         model_name = cls.__name__
       
    52 
       
    53     else:
       
    54         # Look for an "app.Model" relation
       
    55         try:
       
    56             app_label, model_name = relation.split(".")
       
    57         except ValueError:
       
    58             # If we can't split, assume a model in current app
       
    59             app_label = cls._meta.app_label
       
    60             model_name = relation
       
    61 
       
    62     # Try to look up the related model, and if it's already loaded resolve the
       
    63     # string right away. If get_model returns None, it means that the related
       
    64     # model isn't loaded yet, so we need to pend the relation until the class
       
    65     # is prepared.
       
    66     model = get_model(app_label, model_name, False)
       
    67     if model:
       
    68         operation(field, model, cls)
       
    69     else:
       
    70         key = (app_label, model_name)
       
    71         value = (cls, field, operation)
       
    72         pending_lookups.setdefault(key, []).append(value)
       
    73 
       
    74 def do_pending_lookups(sender, **kwargs):
       
    75     """
       
    76     Handle any pending relations to the sending model. Sent from class_prepared.
       
    77     """
       
    78     key = (sender._meta.app_label, sender.__name__)
       
    79     for cls, field, operation in pending_lookups.pop(key, []):
       
    80         operation(field, sender, cls)
       
    81 
       
    82 signals.class_prepared.connect(do_pending_lookups)
       
    83 
       
    84 #HACK
       
    85 class RelatedField(object):
       
    86     def contribute_to_class(self, cls, name):
       
    87         sup = super(RelatedField, self)
       
    88 
       
    89         # Add an accessor to allow easy determination of the related query path for this field
       
    90         self.related_query_name = curry(self._get_related_query_name, cls._meta)
       
    91 
       
    92         if hasattr(sup, 'contribute_to_class'):
       
    93             sup.contribute_to_class(cls, name)
       
    94 
       
    95         if not cls._meta.abstract and self.rel.related_name:
       
    96             self.rel.related_name = self.rel.related_name % {'class': cls.__name__.lower()}
       
    97 
       
    98         other = self.rel.to
       
    99         if isinstance(other, basestring):
       
   100             def resolve_related_class(field, model, cls):
       
   101                 field.rel.to = model
       
   102                 field.do_related_class(model, cls)
       
   103             add_lazy_relation(cls, self, other, resolve_related_class)
       
   104         else:
       
   105             self.do_related_class(other, cls)
       
   106 
       
   107     def set_attributes_from_rel(self):
       
   108         self.name = self.name or (self.rel.to._meta.object_name.lower() + '_' + self.rel.to._meta.pk.name)
       
   109         if self.verbose_name is None:
       
   110             self.verbose_name = self.rel.to._meta.verbose_name
       
   111         self.rel.field_name = self.rel.field_name or self.rel.to._meta.pk.name
       
   112 
       
   113     def do_related_class(self, other, cls):
       
   114         self.set_attributes_from_rel()
       
   115         self.related = RelatedObject(other, cls, self)
       
   116         if not cls._meta.abstract:
       
   117             self.contribute_to_related_class(other, self.related)
       
   118 
       
   119     def get_db_prep_lookup(self, lookup_type, value):
       
   120         # If we are doing a lookup on a Related Field, we must be
       
   121         # comparing object instances. The value should be the PK of value,
       
   122         # not value itself.
       
   123         def pk_trace(value):
       
   124             # Value may be a primary key, or an object held in a relation.
       
   125             # If it is an object, then we need to get the primary key value for
       
   126             # that object. In certain conditions (especially one-to-one relations),
       
   127             # the primary key may itself be an object - so we need to keep drilling
       
   128             # down until we hit a value that can be used for a comparison.
       
   129             v, field = value, None
       
   130             try:
       
   131                 while True:
       
   132                     v, field = getattr(v, v._meta.pk.name), v._meta.pk
       
   133             except AttributeError:
       
   134                 pass
       
   135 
       
   136             if field:
       
   137                 if lookup_type in ('range', 'in'):
       
   138                     v = [v]
       
   139                 v = field.get_db_prep_lookup(lookup_type, v)
       
   140                 if isinstance(v, list):
       
   141                     v = v[0]
       
   142             return v
       
   143 
       
   144         if hasattr(value, 'as_sql') or hasattr(value, '_as_sql'):
       
   145             # If the value has a relabel_aliases method, it will need to
       
   146             # be invoked before the final SQL is evaluated
       
   147             if hasattr(value, 'relabel_aliases'):
       
   148                 return value
       
   149             if hasattr(value, 'as_sql'):
       
   150                 sql, params = value.as_sql()
       
   151             else:
       
   152                 sql, params = value._as_sql()
       
   153             return QueryWrapper(('(%s)' % sql), params)
       
   154 
       
   155         # FIXME: lt and gt are explicitally allowed to make
       
   156         # get_(next/prev)_by_date work; other lookups are not allowed since that
       
   157         # gets messy pretty quick. This is a good candidate for some refactoring
       
   158         # in the future.
       
   159         if lookup_type in ['exact', 'gt', 'lt', 'gte', 'lte']:
       
   160             return [pk_trace(value)]
       
   161         if lookup_type in ('range', 'in'):
       
   162             return [pk_trace(v) for v in value]
       
   163         elif lookup_type == 'isnull':
       
   164             return []
       
   165         raise TypeError, "Related Field has invalid lookup: %s" % lookup_type
       
   166 
       
   167     def _get_related_query_name(self, opts):
       
   168         # This method defines the name that can be used to identify this
       
   169         # related object in a table-spanning query. It uses the lower-cased
       
   170         # object_name by default, but this can be overridden with the
       
   171         # "related_name" option.
       
   172         return self.rel.related_name or opts.object_name.lower()
       
   173 
       
   174 class SingleRelatedObjectDescriptor(object):
       
   175     # This class provides the functionality that makes the related-object
       
   176     # managers available as attributes on a model class, for fields that have
       
   177     # a single "remote" value, on the class pointed to by a related field.
       
   178     # In the example "place.restaurant", the restaurant attribute is a
       
   179     # SingleRelatedObjectDescriptor instance.
       
   180     def __init__(self, related):
       
   181         self.related = related
       
   182         self.cache_name = '_%s_cache' % related.get_accessor_name()
       
   183 
       
   184     def __get__(self, instance, instance_type=None):
       
   185         if instance is None:
       
   186             return self
       
   187         try:
       
   188             return getattr(instance, self.cache_name)
       
   189         except AttributeError:
       
   190             params = {'%s__pk' % self.related.field.name: instance._get_pk_val()}
       
   191             rel_obj = self.related.model._base_manager.get(**params)
       
   192             setattr(instance, self.cache_name, rel_obj)
       
   193             return rel_obj
       
   194 
       
   195     def __set__(self, instance, value):
       
   196         if instance is None:
       
   197             raise AttributeError, "%s must be accessed via instance" % self.related.opts.object_name
       
   198 
       
   199         # The similarity of the code below to the code in
       
   200         # ReverseSingleRelatedObjectDescriptor is annoying, but there's a bunch
       
   201         # of small differences that would make a common base class convoluted.
       
   202 
       
   203         # If null=True, we can assign null here, but otherwise the value needs
       
   204         # to be an instance of the related class.
       
   205         if value is None and self.related.field.null == False:
       
   206             raise ValueError('Cannot assign None: "%s.%s" does not allow null values.' %
       
   207                                 (instance._meta.object_name, self.related.get_accessor_name()))
       
   208         elif value is not None and not isinstance(value, self.related.model):
       
   209             raise ValueError('Cannot assign "%r": "%s.%s" must be a "%s" instance.' %
       
   210                                 (value, instance._meta.object_name,
       
   211                                  self.related.get_accessor_name(), self.related.opts.object_name))
       
   212 
       
   213         # Set the value of the related field to the value of the related object's related field
       
   214         setattr(value, self.related.field.attname, getattr(instance, self.related.field.rel.get_related_field().attname))
       
   215 
       
   216         # Since we already know what the related object is, seed the related
       
   217         # object caches now, too. This avoids another db hit if you get the
       
   218         # object you just set.
       
   219         setattr(instance, self.cache_name, value)
       
   220         setattr(value, self.related.field.get_cache_name(), instance)
       
   221 
       
   222 class ReverseSingleRelatedObjectDescriptor(object):
       
   223     # This class provides the functionality that makes the related-object
       
   224     # managers available as attributes on a model class, for fields that have
       
   225     # a single "remote" value, on the class that defines the related field.
       
   226     # In the example "choice.poll", the poll attribute is a
       
   227     # ReverseSingleRelatedObjectDescriptor instance.
       
   228     def __init__(self, field_with_rel):
       
   229         self.field = field_with_rel
       
   230 
       
   231     def __get__(self, instance, instance_type=None):
       
   232         if instance is None:
       
   233             return self
       
   234 
       
   235         cache_name = self.field.get_cache_name()
       
   236         try:
       
   237             return getattr(instance, cache_name)
       
   238         except AttributeError:
       
   239             val = getattr(instance, self.field.attname)
       
   240             if val is None:
       
   241                 # If NULL is an allowed value, return it.
       
   242                 if self.field.null:
       
   243                     return None
       
   244                 raise self.field.rel.to.DoesNotExist
       
   245             other_field = self.field.rel.get_related_field()
       
   246             if other_field.rel:
       
   247                 params = {'%s__pk' % self.field.rel.field_name: val}
       
   248             else:
       
   249                 params = {'%s__exact' % self.field.rel.field_name: val}
       
   250 
       
   251             # If the related manager indicates that it should be used for
       
   252             # related fields, respect that.
       
   253             rel_mgr = self.field.rel.to._default_manager
       
   254             if getattr(rel_mgr, 'use_for_related_fields', False):
       
   255                 rel_obj = rel_mgr.get(**params)
       
   256             else:
       
   257                 rel_obj = QuerySet(self.field.rel.to).get(**params)
       
   258             setattr(instance, cache_name, rel_obj)
       
   259             return rel_obj
       
   260 
       
   261     def __set__(self, instance, value):
       
   262         if instance is None:
       
   263             raise AttributeError, "%s must be accessed via instance" % self._field.name
       
   264 
       
   265         # If null=True, we can assign null here, but otherwise the value needs
       
   266         # to be an instance of the related class.
       
   267         if value is None and self.field.null == False:
       
   268             raise ValueError('Cannot assign None: "%s.%s" does not allow null values.' %
       
   269                                 (instance._meta.object_name, self.field.name))
       
   270         elif value is not None and not isinstance(value, self.field.rel.to):
       
   271             raise ValueError('Cannot assign "%r": "%s.%s" must be a "%s" instance.' %
       
   272                                 (value, instance._meta.object_name,
       
   273                                  self.field.name, self.field.rel.to._meta.object_name))
       
   274 
       
   275         # If we're setting the value of a OneToOneField to None, we need to clear
       
   276         # out the cache on any old related object. Otherwise, deleting the
       
   277         # previously-related object will also cause this object to be deleted,
       
   278         # which is wrong.
       
   279         if value is None:
       
   280             # Look up the previously-related object, which may still be available
       
   281             # since we've not yet cleared out the related field.
       
   282             # Use the cache directly, instead of the accessor; if we haven't
       
   283             # populated the cache, then we don't care - we're only accessing
       
   284             # the object to invalidate the accessor cache, so there's no
       
   285             # need to populate the cache just to expire it again.
       
   286             related = getattr(instance, self.field.get_cache_name(), None)
       
   287 
       
   288             # If we've got an old related object, we need to clear out its
       
   289             # cache. This cache also might not exist if the related object
       
   290             # hasn't been accessed yet.
       
   291             if related:
       
   292                 cache_name = '_%s_cache' % self.field.related.get_accessor_name()
       
   293                 try:
       
   294                     delattr(related, cache_name)
       
   295                 except AttributeError:
       
   296                     pass
       
   297 
       
   298         # Set the value of the related field
       
   299         try:
       
   300             val = getattr(value, self.field.rel.get_related_field().attname)
       
   301         except AttributeError:
       
   302             val = None
       
   303         setattr(instance, self.field.attname, val)
       
   304 
       
   305         # Since we already know what the related object is, seed the related
       
   306         # object cache now, too. This avoids another db hit if you get the
       
   307         # object you just set.
       
   308         setattr(instance, self.field.get_cache_name(), value)
       
   309 
       
   310 class ForeignRelatedObjectsDescriptor(object):
       
   311     # This class provides the functionality that makes the related-object
       
   312     # managers available as attributes on a model class, for fields that have
       
   313     # multiple "remote" values and have a ForeignKey pointed at them by
       
   314     # some other model. In the example "poll.choice_set", the choice_set
       
   315     # attribute is a ForeignRelatedObjectsDescriptor instance.
       
   316     def __init__(self, related):
       
   317         self.related = related   # RelatedObject instance
       
   318 
       
   319     def __get__(self, instance, instance_type=None):
       
   320         if instance is None:
       
   321             return self
       
   322 
       
   323         return self.create_manager(instance,
       
   324                 self.related.model._default_manager.__class__)
       
   325 
       
   326     def __set__(self, instance, value):
       
   327         if instance is None:
       
   328             raise AttributeError, "Manager must be accessed via instance"
       
   329 
       
   330         manager = self.__get__(instance)
       
   331         # If the foreign key can support nulls, then completely clear the related set.
       
   332         # Otherwise, just move the named objects into the set.
       
   333         if self.related.field.null:
       
   334             manager.clear()
       
   335         manager.add(*value)
       
   336 
       
   337     def delete_manager(self, instance):
       
   338         """
       
   339         Returns a queryset based on the related model's base manager (rather
       
   340         than the default manager, as returned by __get__). Used by
       
   341         Model.delete().
       
   342         """
       
   343         return self.create_manager(instance,
       
   344                 self.related.model._base_manager.__class__)
       
   345 
       
   346     def create_manager(self, instance, superclass):
       
   347         """
       
   348         Creates the managers used by other methods (__get__() and delete()).
       
   349         """
       
   350         rel_field = self.related.field
       
   351         rel_model = self.related.model
       
   352 
       
   353         class RelatedManager(superclass):
       
   354             def get_query_set(self):
       
   355                 return superclass.get_query_set(self).filter(**(self.core_filters))
       
   356 
       
   357             def add(self, *objs):
       
   358                 for obj in objs:
       
   359                     if not isinstance(obj, self.model):
       
   360                         raise TypeError, "'%s' instance expected" % self.model._meta.object_name
       
   361                     setattr(obj, rel_field.name, instance)
       
   362                     obj.save()
       
   363             add.alters_data = True
       
   364 
       
   365             def create(self, **kwargs):
       
   366                 kwargs.update({rel_field.name: instance})
       
   367                 return super(RelatedManager, self).create(**kwargs)
       
   368             create.alters_data = True
       
   369 
       
   370             def get_or_create(self, **kwargs):
       
   371                 # Update kwargs with the related object that this
       
   372                 # ForeignRelatedObjectsDescriptor knows about.
       
   373                 kwargs.update({rel_field.name: instance})
       
   374                 return super(RelatedManager, self).get_or_create(**kwargs)
       
   375             get_or_create.alters_data = True
       
   376 
       
   377             # remove() and clear() are only provided if the ForeignKey can have a value of null.
       
   378             if rel_field.null:
       
   379                 def remove(self, *objs):
       
   380                     val = getattr(instance, rel_field.rel.get_related_field().attname)
       
   381                     for obj in objs:
       
   382                         # Is obj actually part of this descriptor set?
       
   383                         if getattr(obj, rel_field.attname) == val:
       
   384                             setattr(obj, rel_field.name, None)
       
   385                             obj.save()
       
   386                         else:
       
   387                             raise rel_field.rel.to.DoesNotExist, "%r is not related to %r." % (obj, instance)
       
   388                 remove.alters_data = True
       
   389 
       
   390                 def clear(self):
       
   391                     for obj in self.all():
       
   392                         setattr(obj, rel_field.name, None)
       
   393                         obj.save()
       
   394                 clear.alters_data = True
       
   395 
       
   396         manager = RelatedManager()
       
   397         attname = rel_field.rel.get_related_field().name
       
   398         manager.core_filters = {'%s__%s' % (rel_field.name, attname):
       
   399                 getattr(instance, attname)}
       
   400         manager.model = self.related.model
       
   401 
       
   402         return manager
       
   403 
       
   404 def create_many_related_manager(superclass, through=False):
       
   405     """Creates a manager that subclasses 'superclass' (which is a Manager)
       
   406     and adds behavior for many-to-many related objects."""
       
   407     class ManyRelatedManager(superclass):
       
   408         def __init__(self, model=None, core_filters=None, instance=None, symmetrical=None,
       
   409                 join_table=None, source_col_name=None, target_col_name=None):
       
   410             super(ManyRelatedManager, self).__init__()
       
   411             self.core_filters = core_filters
       
   412             self.model = model
       
   413             self.symmetrical = symmetrical
       
   414             self.instance = instance
       
   415             self.join_table = join_table
       
   416             self.source_col_name = source_col_name
       
   417             self.target_col_name = target_col_name
       
   418             self.through = through
       
   419             self._pk_val = self.instance._get_pk_val()
       
   420             if self._pk_val is None:
       
   421                 raise ValueError("%r instance needs to have a primary key value before a many-to-many relationship can be used." % instance.__class__.__name__)
       
   422 
       
   423         def get_query_set(self):
       
   424             return superclass.get_query_set(self)._next_is_sticky().filter(**(self.core_filters))
       
   425 
       
   426         # If the ManyToMany relation has an intermediary model,
       
   427         # the add and remove methods do not exist.
       
   428         if through is None:
       
   429             def add(self, *objs):
       
   430                 self._add_items(self.source_col_name, self.target_col_name, *objs)
       
   431 
       
   432                 # If this is a symmetrical m2m relation to self, add the mirror entry in the m2m table
       
   433                 if self.symmetrical:
       
   434                     self._add_items(self.target_col_name, self.source_col_name, *objs)
       
   435             add.alters_data = True
       
   436 
       
   437             def remove(self, *objs):
       
   438                 self._remove_items(self.source_col_name, self.target_col_name, *objs)
       
   439 
       
   440                 # If this is a symmetrical m2m relation to self, remove the mirror entry in the m2m table
       
   441                 if self.symmetrical:
       
   442                     self._remove_items(self.target_col_name, self.source_col_name, *objs)
       
   443             remove.alters_data = True
       
   444 
       
   445         def clear(self):
       
   446             self._clear_items(self.source_col_name)
       
   447 
       
   448             # If this is a symmetrical m2m relation to self, clear the mirror entry in the m2m table
       
   449             if self.symmetrical:
       
   450                 self._clear_items(self.target_col_name)
       
   451         clear.alters_data = True
       
   452 
       
   453         def create(self, **kwargs):
       
   454             # This check needs to be done here, since we can't later remove this
       
   455             # from the method lookup table, as we do with add and remove.
       
   456             if through is not None:
       
   457                 raise AttributeError, "Cannot use create() on a ManyToManyField which specifies an intermediary model. Use %s's Manager instead." % through
       
   458             new_obj = super(ManyRelatedManager, self).create(**kwargs)
       
   459             self.add(new_obj)
       
   460             return new_obj
       
   461         create.alters_data = True
       
   462 
       
   463         def get_or_create(self, **kwargs):
       
   464             obj, created = \
       
   465                     super(ManyRelatedManager, self).get_or_create(**kwargs)
       
   466             # We only need to add() if created because if we got an object back
       
   467             # from get() then the relationship already exists.
       
   468             if created:
       
   469                 self.add(obj)
       
   470             return obj, created
       
   471         get_or_create.alters_data = True
       
   472 
       
   473         def _add_items(self, source_col_name, target_col_name, *objs):
       
   474             # join_table: name of the m2m link table
       
   475             # source_col_name: the PK colname in join_table for the source object
       
   476             # target_col_name: the PK colname in join_table for the target object
       
   477             # *objs - objects to add. Either object instances, or primary keys of object instances.
       
   478 
       
   479             # If there aren't any objects, there is nothing to do.
       
   480             if objs:
       
   481                 from django.db.models.base import Model
       
   482                 # Check that all the objects are of the right type
       
   483                 new_ids = set()
       
   484                 for obj in objs:
       
   485                     if isinstance(obj, self.model):
       
   486                         new_ids.add(obj._get_pk_val())
       
   487                     elif isinstance(obj, Model):
       
   488                         raise TypeError, "'%s' instance expected" % self.model._meta.object_name
       
   489                     else:
       
   490                         new_ids.add(obj)
       
   491                 # Add the newly created or already existing objects to the join table.
       
   492                 # First find out which items are already added, to avoid adding them twice
       
   493                 cursor = connection.cursor()
       
   494                 cursor.execute("SELECT %s FROM %s WHERE %s = %%s AND %s IN (%s)" % \
       
   495                     (target_col_name, self.join_table, source_col_name,
       
   496                     target_col_name, ",".join(['%s'] * len(new_ids))),
       
   497                     [self._pk_val] + list(new_ids))
       
   498                 existing_ids = set([row[0] for row in cursor.fetchall()])
       
   499 
       
   500                 # Add the ones that aren't there already
       
   501                 for obj_id in (new_ids - existing_ids):
       
   502                     cursor.execute("INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \
       
   503                         (self.join_table, source_col_name, target_col_name),
       
   504                         [self._pk_val, obj_id])
       
   505                 transaction.commit_unless_managed()
       
   506 
       
   507         def _remove_items(self, source_col_name, target_col_name, *objs):
       
   508             # source_col_name: the PK colname in join_table for the source object
       
   509             # target_col_name: the PK colname in join_table for the target object
       
   510             # *objs - objects to remove
       
   511 
       
   512             # If there aren't any objects, there is nothing to do.
       
   513             if objs:
       
   514                 # Check that all the objects are of the right type
       
   515                 old_ids = set()
       
   516                 for obj in objs:
       
   517                     if isinstance(obj, self.model):
       
   518                         old_ids.add(obj._get_pk_val())
       
   519                     else:
       
   520                         old_ids.add(obj)
       
   521                 # Remove the specified objects from the join table
       
   522                 cursor = connection.cursor()
       
   523                 cursor.execute("DELETE FROM %s WHERE %s = %%s AND %s IN (%s)" % \
       
   524                     (self.join_table, source_col_name,
       
   525                     target_col_name, ",".join(['%s'] * len(old_ids))),
       
   526                     [self._pk_val] + list(old_ids))
       
   527                 transaction.commit_unless_managed()
       
   528 
       
   529         def _clear_items(self, source_col_name):
       
   530             # source_col_name: the PK colname in join_table for the source object
       
   531             cursor = connection.cursor()
       
   532             cursor.execute("DELETE FROM %s WHERE %s = %%s" % \
       
   533                 (self.join_table, source_col_name),
       
   534                 [self._pk_val])
       
   535             transaction.commit_unless_managed()
       
   536 
       
   537     return ManyRelatedManager
       
   538 
       
   539 class ManyRelatedObjectsDescriptor(object):
       
   540     # This class provides the functionality that makes the related-object
       
   541     # managers available as attributes on a model class, for fields that have
       
   542     # multiple "remote" values and have a ManyToManyField pointed at them by
       
   543     # some other model (rather than having a ManyToManyField themselves).
       
   544     # In the example "publication.article_set", the article_set attribute is a
       
   545     # ManyRelatedObjectsDescriptor instance.
       
   546     def __init__(self, related):
       
   547         self.related = related   # RelatedObject instance
       
   548 
       
   549     def __get__(self, instance, instance_type=None):
       
   550         if instance is None:
       
   551             return self
       
   552 
       
   553         # Dynamically create a class that subclasses the related
       
   554         # model's default manager.
       
   555         rel_model = self.related.model
       
   556         superclass = rel_model._default_manager.__class__
       
   557         RelatedManager = create_many_related_manager(superclass, self.related.field.rel.through)
       
   558 
       
   559         qn = connection.ops.quote_name
       
   560         manager = RelatedManager(
       
   561             model=rel_model,
       
   562             core_filters={'%s__pk' % self.related.field.name: instance._get_pk_val()},
       
   563             instance=instance,
       
   564             symmetrical=False,
       
   565             join_table=qn(self.related.field.m2m_db_table()),
       
   566             source_col_name=qn(self.related.field.m2m_reverse_name()),
       
   567             target_col_name=qn(self.related.field.m2m_column_name())
       
   568         )
       
   569 
       
   570         return manager
       
   571 
       
   572     def __set__(self, instance, value):
       
   573         if instance is None:
       
   574             raise AttributeError, "Manager must be accessed via instance"
       
   575 
       
   576         through = getattr(self.related.field.rel, 'through', None)
       
   577         if through is not None:
       
   578             raise AttributeError, "Cannot set values on a ManyToManyField which specifies an intermediary model. Use %s's Manager instead." % through
       
   579 
       
   580         manager = self.__get__(instance)
       
   581         manager.clear()
       
   582         manager.add(*value)
       
   583 
       
   584 class ReverseManyRelatedObjectsDescriptor(object):
       
   585     # This class provides the functionality that makes the related-object
       
   586     # managers available as attributes on a model class, for fields that have
       
   587     # multiple "remote" values and have a ManyToManyField defined in their
       
   588     # model (rather than having another model pointed *at* them).
       
   589     # In the example "article.publications", the publications attribute is a
       
   590     # ReverseManyRelatedObjectsDescriptor instance.
       
   591     def __init__(self, m2m_field):
       
   592         self.field = m2m_field
       
   593 
       
   594     def __get__(self, instance, instance_type=None):
       
   595         if instance is None:
       
   596             return self
       
   597 
       
   598         # Dynamically create a class that subclasses the related
       
   599         # model's default manager.
       
   600         rel_model=self.field.rel.to
       
   601         superclass = rel_model._default_manager.__class__
       
   602         RelatedManager = create_many_related_manager(superclass, self.field.rel.through)
       
   603 
       
   604         qn = connection.ops.quote_name
       
   605         manager = RelatedManager(
       
   606             model=rel_model,
       
   607             core_filters={'%s__pk' % self.field.related_query_name(): instance._get_pk_val()},
       
   608             instance=instance,
       
   609             symmetrical=(self.field.rel.symmetrical and isinstance(instance, rel_model)),
       
   610             join_table=qn(self.field.m2m_db_table()),
       
   611             source_col_name=qn(self.field.m2m_column_name()),
       
   612             target_col_name=qn(self.field.m2m_reverse_name())
       
   613         )
       
   614 
       
   615         return manager
       
   616 
       
   617     def __set__(self, instance, value):
       
   618         if instance is None:
       
   619             raise AttributeError, "Manager must be accessed via instance"
       
   620 
       
   621         through = getattr(self.field.rel, 'through', None)
       
   622         if through is not None:
       
   623             raise AttributeError, "Cannot set values on a ManyToManyField which specifies an intermediary model.  Use %s's Manager instead." % through
       
   624 
       
   625         manager = self.__get__(instance)
       
   626         manager.clear()
       
   627         manager.add(*value)
       
   628 
       
   629 class ManyToOneRel(object):
       
   630     def __init__(self, to, field_name, related_name=None,
       
   631             limit_choices_to=None, lookup_overrides=None, parent_link=False):
       
   632         try:
       
   633             to._meta
       
   634         except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT
       
   635             assert isinstance(to, basestring), "'to' must be either a model, a model name or the string %r" % RECURSIVE_RELATIONSHIP_CONSTANT
       
   636         self.to, self.field_name = to, field_name
       
   637         self.related_name = related_name
       
   638         if limit_choices_to is None:
       
   639             limit_choices_to = {}
       
   640         self.limit_choices_to = limit_choices_to
       
   641         self.lookup_overrides = lookup_overrides or {}
       
   642         self.multiple = True
       
   643         self.parent_link = parent_link
       
   644 
       
   645     def get_related_field(self):
       
   646         """
       
   647         Returns the Field in the 'to' object to which this relationship is
       
   648         tied.
       
   649         """
       
   650         data = self.to._meta.get_field_by_name(self.field_name)
       
   651         if not data[2]:
       
   652             raise FieldDoesNotExist("No related field named '%s'" %
       
   653                     self.field_name)
       
   654         return data[0]
       
   655 
       
   656 class OneToOneRel(ManyToOneRel):
       
   657     def __init__(self, to, field_name, related_name=None,
       
   658             limit_choices_to=None, lookup_overrides=None, parent_link=False):
       
   659         super(OneToOneRel, self).__init__(to, field_name,
       
   660                 related_name=related_name, limit_choices_to=limit_choices_to,
       
   661                 lookup_overrides=lookup_overrides, parent_link=parent_link)
       
   662         self.multiple = False
       
   663 
       
   664 class ManyToManyRel(object):
       
   665     def __init__(self, to, related_name=None, limit_choices_to=None,
       
   666             symmetrical=True, through=None):
       
   667         self.to = to
       
   668         self.related_name = related_name
       
   669         if limit_choices_to is None:
       
   670             limit_choices_to = {}
       
   671         self.limit_choices_to = limit_choices_to
       
   672         self.symmetrical = symmetrical
       
   673         self.multiple = True
       
   674         self.through = through
       
   675 
       
   676     def get_related_field(self):
       
   677         """
       
   678         Returns the field in the to' object to which this relationship is tied
       
   679         (this is always the primary key on the target model). Provided for
       
   680         symmetry with ManyToOneRel.
       
   681         """
       
   682         return self.to._meta.pk
       
   683 
       
   684 class ForeignKey(RelatedField, Field):
       
   685     empty_strings_allowed = False
       
   686     def __init__(self, to, to_field=None, rel_class=ManyToOneRel, **kwargs):
       
   687         try:
       
   688             to_name = to._meta.object_name.lower()
       
   689         except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT
       
   690             assert isinstance(to, basestring), "%s(%r) is invalid. First parameter to ForeignKey must be either a model, a model name, or the string %r" % (self.__class__.__name__, to, RECURSIVE_RELATIONSHIP_CONSTANT)
       
   691         else:
       
   692             assert not to._meta.abstract, "%s cannot define a relation with abstract class %s" % (self.__class__.__name__, to._meta.object_name)
       
   693             to_field = to_field or to._meta.pk.name
       
   694         kwargs['verbose_name'] = kwargs.get('verbose_name', None)
       
   695 
       
   696         kwargs['rel'] = rel_class(to, to_field,
       
   697             related_name=kwargs.pop('related_name', None),
       
   698             limit_choices_to=kwargs.pop('limit_choices_to', None),
       
   699             lookup_overrides=kwargs.pop('lookup_overrides', None),
       
   700             parent_link=kwargs.pop('parent_link', False))
       
   701         Field.__init__(self, **kwargs)
       
   702 
       
   703         self.db_index = True
       
   704 
       
   705     def get_attname(self):
       
   706         return '%s_id' % self.name
       
   707 
       
   708     def get_validator_unique_lookup_type(self):
       
   709         return '%s__%s__exact' % (self.name, self.rel.get_related_field().name)
       
   710 
       
   711     def get_default(self):
       
   712         "Here we check if the default value is an object and return the to_field if so."
       
   713         field_default = super(ForeignKey, self).get_default()
       
   714         if isinstance(field_default, self.rel.to):
       
   715             return getattr(field_default, self.rel.get_related_field().attname)
       
   716         return field_default
       
   717 
       
   718     def get_db_prep_save(self, value):
       
   719         if value == '' or value == None:
       
   720             return None
       
   721         else:
       
   722             return self.rel.get_related_field().get_db_prep_save(value)
       
   723 
       
   724     def value_to_string(self, obj):
       
   725         if not obj:
       
   726             # In required many-to-one fields with only one available choice,
       
   727             # select that one available choice. Note: For SelectFields
       
   728             # we have to check that the length of choices is *2*, not 1,
       
   729             # because SelectFields always have an initial "blank" value.
       
   730             if not self.blank and self.choices:
       
   731                 choice_list = self.get_choices_default()
       
   732                 if len(choice_list) == 2:
       
   733                     return smart_unicode(choice_list[1][0])
       
   734         return Field.value_to_string(self, obj)
       
   735 
       
   736     def contribute_to_class(self, cls, name):
       
   737         super(ForeignKey, self).contribute_to_class(cls, name)
       
   738         setattr(cls, self.name, ReverseSingleRelatedObjectDescriptor(self))
       
   739         if isinstance(self.rel.to, basestring):
       
   740             target = self.rel.to
       
   741         else:
       
   742             target = self.rel.to._meta.db_table
       
   743         cls._meta.duplicate_targets[self.column] = (target, "o2m")
       
   744 
       
   745     def contribute_to_related_class(self, cls, related):
       
   746         setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related))
       
   747 
       
   748     def formfield(self, **kwargs):
       
   749         defaults = {
       
   750             'form_class': forms.ModelChoiceField,
       
   751             'queryset': self.rel.to._default_manager.complex_filter(
       
   752                                                     self.rel.limit_choices_to),
       
   753             'to_field_name': self.rel.field_name,
       
   754         }
       
   755         defaults.update(kwargs)
       
   756         return super(ForeignKey, self).formfield(**defaults)
       
   757 
       
   758     def db_type(self):
       
   759         # The database column type of a ForeignKey is the column type
       
   760         # of the field to which it points. An exception is if the ForeignKey
       
   761         # points to an AutoField/PositiveIntegerField/PositiveSmallIntegerField,
       
   762         # in which case the column type is simply that of an IntegerField.
       
   763         # If the database needs similar types for key fields however, the only
       
   764         # thing we can do is making AutoField an IntegerField.
       
   765         rel_field = self.rel.get_related_field()
       
   766         if (isinstance(rel_field, AutoField) or
       
   767                 (not connection.features.related_fields_match_type and
       
   768                 isinstance(rel_field, (PositiveIntegerField,
       
   769                                        PositiveSmallIntegerField)))):
       
   770             return IntegerField().db_type()
       
   771         return rel_field.db_type()
       
   772 
       
   773 class OneToOneField(ForeignKey):
       
   774     """
       
   775     A OneToOneField is essentially the same as a ForeignKey, with the exception
       
   776     that always carries a "unique" constraint with it and the reverse relation
       
   777     always returns the object pointed to (since there will only ever be one),
       
   778     rather than returning a list.
       
   779     """
       
   780     def __init__(self, to, to_field=None, **kwargs):
       
   781         kwargs['unique'] = True
       
   782         super(OneToOneField, self).__init__(to, to_field, OneToOneRel, **kwargs)
       
   783 
       
   784     def contribute_to_related_class(self, cls, related):
       
   785         setattr(cls, related.get_accessor_name(),
       
   786                 SingleRelatedObjectDescriptor(related))
       
   787 
       
   788     def formfield(self, **kwargs):
       
   789         if self.rel.parent_link:
       
   790             return None
       
   791         return super(OneToOneField, self).formfield(**kwargs)
       
   792 
       
   793 class ManyToManyField(RelatedField, Field):
       
   794     def __init__(self, to, **kwargs):
       
   795         try:
       
   796             assert not to._meta.abstract, "%s cannot define a relation with abstract class %s" % (self.__class__.__name__, to._meta.object_name)
       
   797         except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT
       
   798             assert isinstance(to, basestring), "%s(%r) is invalid. First parameter to ManyToManyField must be either a model, a model name, or the string %r" % (self.__class__.__name__, to, RECURSIVE_RELATIONSHIP_CONSTANT)
       
   799 
       
   800         kwargs['verbose_name'] = kwargs.get('verbose_name', None)
       
   801         kwargs['rel'] = ManyToManyRel(to,
       
   802             related_name=kwargs.pop('related_name', None),
       
   803             limit_choices_to=kwargs.pop('limit_choices_to', None),
       
   804             symmetrical=kwargs.pop('symmetrical', True),
       
   805             through=kwargs.pop('through', None))
       
   806 
       
   807         self.db_table = kwargs.pop('db_table', None)
       
   808         if kwargs['rel'].through is not None:
       
   809             self.creates_table = False
       
   810             assert self.db_table is None, "Cannot specify a db_table if an intermediary model is used."
       
   811         else:
       
   812             self.creates_table = True
       
   813 
       
   814         Field.__init__(self, **kwargs)
       
   815 
       
   816         msg = ugettext_lazy('Hold down "Control", or "Command" on a Mac, to select more than one.')
       
   817         self.help_text = string_concat(self.help_text, ' ', msg)
       
   818 
       
   819     def get_choices_default(self):
       
   820         return Field.get_choices(self, include_blank=False)
       
   821 
       
   822     def _get_m2m_db_table(self, opts):
       
   823         "Function that can be curried to provide the m2m table name for this relation"
       
   824         if self.rel.through is not None:
       
   825             return self.rel.through_model._meta.db_table
       
   826         elif self.db_table:
       
   827             return self.db_table
       
   828         else:
       
   829             return util.truncate_name('%s_%s' % (opts.db_table, self.name),
       
   830                                       connection.ops.max_name_length())
       
   831 
       
   832     def _get_m2m_column_name(self, related):
       
   833         "Function that can be curried to provide the source column name for the m2m table"
       
   834         try:
       
   835             return self._m2m_column_name_cache
       
   836         except:
       
   837             if self.rel.through is not None:
       
   838                 for f in self.rel.through_model._meta.fields:
       
   839                     if hasattr(f,'rel') and f.rel and f.rel.to == related.model:
       
   840                         self._m2m_column_name_cache = f.column
       
   841                         break
       
   842             # If this is an m2m relation to self, avoid the inevitable name clash
       
   843             elif related.model == related.parent_model:
       
   844                 self._m2m_column_name_cache = 'from_' + related.model._meta.object_name.lower() + '_id'
       
   845             else:
       
   846                 self._m2m_column_name_cache = related.model._meta.object_name.lower() + '_id'
       
   847 
       
   848             # Return the newly cached value
       
   849             return self._m2m_column_name_cache
       
   850 
       
   851     def _get_m2m_reverse_name(self, related):
       
   852         "Function that can be curried to provide the related column name for the m2m table"
       
   853         try:
       
   854             return self._m2m_reverse_name_cache
       
   855         except:
       
   856             if self.rel.through is not None:
       
   857                 found = False
       
   858                 for f in self.rel.through_model._meta.fields:
       
   859                     if hasattr(f,'rel') and f.rel and f.rel.to == related.parent_model:
       
   860                         if related.model == related.parent_model:
       
   861                             # If this is an m2m-intermediate to self,
       
   862                             # the first foreign key you find will be
       
   863                             # the source column. Keep searching for
       
   864                             # the second foreign key.
       
   865                             if found:
       
   866                                 self._m2m_reverse_name_cache = f.column
       
   867                                 break
       
   868                             else:
       
   869                                 found = True
       
   870                         else:
       
   871                             self._m2m_reverse_name_cache = f.column
       
   872                             break
       
   873             # If this is an m2m relation to self, avoid the inevitable name clash
       
   874             elif related.model == related.parent_model:
       
   875                 self._m2m_reverse_name_cache = 'to_' + related.parent_model._meta.object_name.lower() + '_id'
       
   876             else:
       
   877                 self._m2m_reverse_name_cache = related.parent_model._meta.object_name.lower() + '_id'
       
   878 
       
   879             # Return the newly cached value
       
   880             return self._m2m_reverse_name_cache
       
   881 
       
   882     def isValidIDList(self, field_data, all_data):
       
   883         "Validates that the value is a valid list of foreign keys"
       
   884         mod = self.rel.to
       
   885         try:
       
   886             pks = map(int, field_data.split(','))
       
   887         except ValueError:
       
   888             # the CommaSeparatedIntegerField validator will catch this error
       
   889             return
       
   890         objects = mod._default_manager.in_bulk(pks)
       
   891         if len(objects) != len(pks):
       
   892             badkeys = [k for k in pks if k not in objects]
       
   893             raise exceptions.ValidationError(
       
   894                 ungettext("Please enter valid %(self)s IDs. The value %(value)r is invalid.",
       
   895                           "Please enter valid %(self)s IDs. The values %(value)r are invalid.",
       
   896                           len(badkeys)) % {
       
   897                 'self': self.verbose_name,
       
   898                 'value': len(badkeys) == 1 and badkeys[0] or tuple(badkeys),
       
   899             })
       
   900 
       
   901     def value_to_string(self, obj):
       
   902         data = ''
       
   903         if obj:
       
   904             qs = getattr(obj, self.name).all()
       
   905             data = [instance._get_pk_val() for instance in qs]
       
   906         else:
       
   907             # In required many-to-many fields with only one available choice,
       
   908             # select that one available choice.
       
   909             if not self.blank:
       
   910                 choices_list = self.get_choices_default()
       
   911                 if len(choices_list) == 1:
       
   912                     data = [choices_list[0][0]]
       
   913         return smart_unicode(data)
       
   914 
       
   915     def contribute_to_class(self, cls, name):
       
   916         # To support multiple relations to self, it's useful to have a non-None
       
   917         # related name on symmetrical relations for internal reasons. The
       
   918         # concept doesn't make a lot of sense externally ("you want me to
       
   919         # specify *what* on my non-reversible relation?!"), so we set it up
       
   920         # automatically. The funky name reduces the chance of an accidental
       
   921         # clash.
       
   922         if self.rel.symmetrical and self.rel.to == "self" and self.rel.related_name is None:
       
   923             self.rel.related_name = "%s_rel_+" % name
       
   924 
       
   925         super(ManyToManyField, self).contribute_to_class(cls, name)
       
   926         # Add the descriptor for the m2m relation
       
   927         setattr(cls, self.name, ReverseManyRelatedObjectsDescriptor(self))
       
   928 
       
   929         # Set up the accessor for the m2m table name for the relation
       
   930         self.m2m_db_table = curry(self._get_m2m_db_table, cls._meta)
       
   931 
       
   932         # Populate some necessary rel arguments so that cross-app relations
       
   933         # work correctly.
       
   934         if isinstance(self.rel.through, basestring):
       
   935             def resolve_through_model(field, model, cls):
       
   936                 field.rel.through_model = model
       
   937             add_lazy_relation(cls, self, self.rel.through, resolve_through_model)
       
   938         elif self.rel.through:
       
   939             self.rel.through_model = self.rel.through
       
   940             self.rel.through = self.rel.through._meta.object_name
       
   941 
       
   942         if isinstance(self.rel.to, basestring):
       
   943             target = self.rel.to
       
   944         else:
       
   945             target = self.rel.to._meta.db_table
       
   946         cls._meta.duplicate_targets[self.column] = (target, "m2m")
       
   947 
       
   948     def contribute_to_related_class(self, cls, related):
       
   949         # m2m relations to self do not have a ManyRelatedObjectsDescriptor,
       
   950         # as it would be redundant - unless the field is non-symmetrical.
       
   951         if related.model != related.parent_model or not self.rel.symmetrical:
       
   952             # Add the descriptor for the m2m relation
       
   953             setattr(cls, related.get_accessor_name(), ManyRelatedObjectsDescriptor(related))
       
   954 
       
   955         # Set up the accessors for the column names on the m2m table
       
   956         self.m2m_column_name = curry(self._get_m2m_column_name, related)
       
   957         self.m2m_reverse_name = curry(self._get_m2m_reverse_name, related)
       
   958 
       
   959     def set_attributes_from_rel(self):
       
   960         pass
       
   961 
       
   962     def value_from_object(self, obj):
       
   963         "Returns the value of this field in the given model instance."
       
   964         return getattr(obj, self.attname).all()
       
   965 
       
   966     def save_form_data(self, instance, data):
       
   967         setattr(instance, self.attname, data)
       
   968 
       
   969     def formfield(self, **kwargs):
       
   970         defaults = {'form_class': forms.ModelMultipleChoiceField, 'queryset': self.rel.to._default_manager.complex_filter(self.rel.limit_choices_to)}
       
   971         defaults.update(kwargs)
       
   972         # If initial is passed in, it's a list of related objects, but the
       
   973         # MultipleChoiceField takes a list of IDs.
       
   974         if defaults.get('initial') is not None:
       
   975             initial = defaults['initial']
       
   976             if callable(initial):
       
   977                 initial = initial()
       
   978             defaults['initial'] = [i._get_pk_val() for i in initial]
       
   979         return super(ManyToManyField, self).formfield(**defaults)
       
   980 
       
   981     def db_type(self):
       
   982         # A ManyToManyField is not represented by a single column,
       
   983         # so return None.
       
   984         return None