﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
11956	ReverseManyRelatedObjectsDescriptor wrongly assumes symmetry between inherited objects	Nicolas Dietrich	malcalypse	"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)
}}}"		closed	Database layer (models, ORM)	1.1		fixed			Accepted	0	0	0	0	0	0
