#11956: ReverseManyRelatedObjectsDescriptor wrongly assumes symmetry between
inherited objects
------------------------------------------+---------------------------------
 Reporter:  nidi                          |       Owner:  nobody    
   Status:  new                           |   Milestone:            
Component:  Database layer (models, ORM)  |     Version:  1.1       
 Keywords:                                |       Stage:  Unreviewed
Has_patch:  0                             |  
------------------------------------------+---------------------------------
 Symmetrical many-to-many do only make sense between objects of the same
 model type, as described in the documentation. However,
 ''!ReverseManyRelatedObjectDescriptors'' wrongly assume symmetricity when
 defining a ''!ManyToManyField'' from an inherited model towards a base
 class, as in the following model definition:

 {{{
 class BaseModel(models.Model):
     pass

 class ChildModel(BaseModel):
     many = models.ManyToManyField(BaseModel, related_name='many_children')
 }}}


 This results in the following integrity error in case Postgres is used (-
 for some reason, the problem does not occur using sqlite!):

 {{{
 > from symmetricbug.models import *
 > base = BaseModel.objects.create()
 > child = ChildModel.objects.create()
 > child.many.add(base)

 [...]

 /usr/lib64/python2.5/site-packages/django/db/models/fields/related.pyc in
 add(self, *objs)
     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

 [...]

 IntegrityError: insert or update on table "symmetricbug_childmodel_many"
 violates foreign key constraint
 "symmetricbug_childmodel_many_childmodel_id_fkey"
 DETAIL:  Key (childmodel_id)=(1) is not present in table
 "symmetricbug_childmodel".
 }}}

 This obviously does not make any sense, because there is no
 ''!ChildModel'' object with id 1. The reason is that
 ''!ReverseManyRelatedObjectsDescriptor'' wrongly assumes symmetricity:

 `django.db.models.fields.related:609` is
 {{{
 symmetrical=(self.field.rel.symmetrical and isinstance(instance,
 rel_model)),
 }}}
 and should be something alike
 {{{
 symmetrical=(self.field.rel.symmetrical and instance.__class__ ==
 rel_model.__class__),
 }}}
 to be aware of subclasses.


 '''Workaround''': Use ''symmetrical=False'' in the model definition:
 {{{
 class ChildModel(BaseModel):
     many = models.ManyToManyField(BaseModel, related_name='many_children',
 symmetrical=False)
 }}}

-- 
Ticket URL: <http://code.djangoproject.com/ticket/11956>
Django <http://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to