Fixed #28988 -- Fixed queries when a GenericRelation is used with multi-table inheritance.

This commit is contained in:
robwa 2018-03-13 03:42:48 +01:00 committed by Tim Graham
parent b639bcc250
commit 4ab027b944
4 changed files with 22 additions and 2 deletions

View File

@ -283,6 +283,8 @@ class GenericRelation(ForeignObject):
rel_class = GenericRel rel_class = GenericRel
mti_inherited = False
def __init__(self, to, object_id_field='object_id', content_type_field='content_type', def __init__(self, to, object_id_field='object_id', content_type_field='content_type',
for_concrete_model=True, related_query_name=None, limit_choices_to=None, **kwargs): for_concrete_model=True, related_query_name=None, limit_choices_to=None, **kwargs):
kwargs['rel'] = self.rel_class( kwargs['rel'] = self.rel_class(
@ -427,6 +429,12 @@ class GenericRelation(ForeignObject):
kwargs['private_only'] = True kwargs['private_only'] = True
super().contribute_to_class(cls, name, **kwargs) super().contribute_to_class(cls, name, **kwargs)
self.model = cls self.model = cls
# Disable the reverse relation for fields inherited by subclasses of a
# model in multi-table inheritance. The reverse relation points to the
# field of the base model.
if self.mti_inherited:
self.remote_field.related_name = '+'
self.remote_field.related_query_name = None
setattr(cls, self.name, ReverseGenericManyToOneDescriptor(self.remote_field)) setattr(cls, self.name, ReverseGenericManyToOneDescriptor(self.remote_field))
# Add get_RELATED_order() and set_RELATED_order() to the model this # Add get_RELATED_order() and set_RELATED_order() to the model this

View File

@ -278,7 +278,9 @@ class ModelBase(type):
) )
) )
else: else:
new_class.add_to_class(field.name, copy.deepcopy(field)) field = copy.deepcopy(field)
field.mti_inherited = True
new_class.add_to_class(field.name, field)
# Copy indexes so that index names are unique when models extend an # Copy indexes so that index names are unique when models extend an
# abstract model. # abstract model.

View File

@ -26,7 +26,7 @@ class LinkProxy(Link):
class Place(models.Model): class Place(models.Model):
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
links = GenericRelation(Link) links = GenericRelation(Link, related_query_name='places')
link_proxy = GenericRelation(LinkProxy) link_proxy = GenericRelation(LinkProxy)
def __str__(self): def __str__(self):

View File

@ -263,3 +263,13 @@ class GenericRelationTests(TestCase):
place = Place.objects.create() place = Place.objects.create()
Link.objects.create(content_object=place) Link.objects.create(content_object=place)
self.assertEqual(Place.objects.get(link_proxy__object_id=place.id), place) self.assertEqual(Place.objects.get(link_proxy__object_id=place.id), place)
def test_generic_reverse_relation_with_mti(self):
"""
Filtering with a reverse generic relation, where the GenericRelation
comes from multi-table inheritance.
"""
place = Place.objects.create(name='Test Place')
link = Link.objects.create(content_object=place)
result = Link.objects.filter(places=place)
self.assertCountEqual(result, [link])