#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
-~----------~----~----~----~------~----~------~--~---