Fixed #24002 -- GenericRelation filtering targets related model's pk
Previously Publisher.objects.filter(book=val) would target book.object_id if book is a GenericRelation. This is inconsistent to filtering over reverse foreign key relations, where the target is the related model's primary key.
This commit is contained in:
parent
104aaab704
commit
1c5cbf5e5d
|
@ -307,7 +307,7 @@ class GenericRelation(ForeignObject):
|
||||||
|
|
||||||
def get_path_info(self):
|
def get_path_info(self):
|
||||||
opts = self.rel.to._meta
|
opts = self.rel.to._meta
|
||||||
target = opts.get_field_by_name(self.object_id_field_name)[0]
|
target = opts.pk
|
||||||
return [PathInfo(self.model._meta, opts, (target,), self.rel, True, False)]
|
return [PathInfo(self.model._meta, opts, (target,), self.rel, True, False)]
|
||||||
|
|
||||||
def get_reverse_path_info(self):
|
def get_reverse_path_info(self):
|
||||||
|
|
|
@ -220,15 +220,18 @@ class GenericRelationTests(TestCase):
|
||||||
|
|
||||||
def test_annotate(self):
|
def test_annotate(self):
|
||||||
hs1 = HasLinkThing.objects.create()
|
hs1 = HasLinkThing.objects.create()
|
||||||
|
hs2 = HasLinkThing.objects.create()
|
||||||
|
HasLinkThing.objects.create()
|
||||||
b = Board.objects.create(name=str(hs1.pk))
|
b = Board.objects.create(name=str(hs1.pk))
|
||||||
|
Link.objects.create(content_object=hs2)
|
||||||
l = Link.objects.create(content_object=hs1)
|
l = Link.objects.create(content_object=hs1)
|
||||||
Link.objects.create(content_object=b)
|
Link.objects.create(content_object=b)
|
||||||
qs = HasLinkThing.objects.annotate(Sum('links'))
|
qs = HasLinkThing.objects.annotate(Sum('links')).filter(pk=hs1.pk)
|
||||||
# If content_type restriction isn't in the query's join condition,
|
# If content_type restriction isn't in the query's join condition,
|
||||||
# then wrong results are produced here as the link to b will also match
|
# then wrong results are produced here as the link to b will also match
|
||||||
# (b and hs1 have equal pks).
|
# (b and hs1 have equal pks).
|
||||||
self.assertEqual(qs.count(), 1)
|
self.assertEqual(qs.count(), 1)
|
||||||
self.assertEqual(qs[0].links__sum, hs1.id)
|
self.assertEqual(qs[0].links__sum, l.id)
|
||||||
l.delete()
|
l.delete()
|
||||||
# Now if we don't have proper left join, we will not produce any
|
# Now if we don't have proper left join, we will not produce any
|
||||||
# results at all here.
|
# results at all here.
|
||||||
|
@ -241,6 +244,15 @@ class GenericRelationTests(TestCase):
|
||||||
self.assertEqual(qs.filter(links__sum__isnull=True).count(), 1)
|
self.assertEqual(qs.filter(links__sum__isnull=True).count(), 1)
|
||||||
self.assertEqual(qs.filter(links__sum__isnull=False).count(), 0)
|
self.assertEqual(qs.filter(links__sum__isnull=False).count(), 0)
|
||||||
|
|
||||||
|
def test_filter_targets_related_pk(self):
|
||||||
|
HasLinkThing.objects.create()
|
||||||
|
hs2 = HasLinkThing.objects.create()
|
||||||
|
l = Link.objects.create(content_object=hs2)
|
||||||
|
self.assertNotEqual(l.object_id, l.pk)
|
||||||
|
self.assertQuerysetEqual(
|
||||||
|
HasLinkThing.objects.filter(links=l.pk),
|
||||||
|
[hs2], lambda x: x)
|
||||||
|
|
||||||
def test_editable_generic_rel(self):
|
def test_editable_generic_rel(self):
|
||||||
GenericRelationForm = modelform_factory(HasLinkThing, fields='__all__')
|
GenericRelationForm = modelform_factory(HasLinkThing, fields='__all__')
|
||||||
form = GenericRelationForm()
|
form = GenericRelationForm()
|
||||||
|
|
Loading…
Reference in New Issue