diff options
| author | Morgan Wahl <morgan@addgene.org> | 2017-12-05 16:08:50 -0500 |
|---|---|---|
| committer | Morgan Wahl <morgan@addgene.org> | 2017-12-07 09:34:54 -0500 |
| commit | 35222035029863f95769e2e59beeeb953d125689 (patch) | |
| tree | c4a9537b79c35340271e01e6de1463d6ed0983f7 | |
| parent | 1decd0197d241b27d54bb12eca04b7e89a9ccba6 (diff) | |
[1.11.x] Refs #28856 -- Fixed caching of a GenericForeignKey pointing to a model that uses more than one level of MTI.
| -rw-r--r-- | django/contrib/contenttypes/fields.py | 10 | ||||
| -rw-r--r-- | docs/releases/1.11.9.txt | 4 | ||||
| -rw-r--r-- | tests/generic_relations_regress/models.py | 6 | ||||
| -rw-r--r-- | tests/generic_relations_regress/tests.py | 12 |
4 files changed, 28 insertions, 4 deletions
diff --git a/django/contrib/contenttypes/fields.py b/django/contrib/contenttypes/fields.py index 84aac50814..11afe4df33 100644 --- a/django/contrib/contenttypes/fields.py +++ b/django/contrib/contenttypes/fields.py @@ -237,7 +237,15 @@ class GenericForeignKey(object): pk = rel_obj._meta.pk # If the primary key is a remote field, use the referenced # field's to_python(). - pk_to_python = pk.target_field.to_python if pk.remote_field else pk.to_python + to_python_field = pk + # Out of an abundance of caution, avoid infinite loops. + seen = {to_python_field} + while to_python_field.remote_field: + to_python_field = to_python_field.target_field + if to_python_field in seen: + break + seen.add(to_python_field) + pk_to_python = to_python_field.to_python if pk_to_python(pk_val) != rel_obj._get_pk_val(): rel_obj = None diff --git a/docs/releases/1.11.9.txt b/docs/releases/1.11.9.txt index fa480d44bc..10fe3d9f96 100644 --- a/docs/releases/1.11.9.txt +++ b/docs/releases/1.11.9.txt @@ -17,3 +17,7 @@ Bugfixes * Fixed incorrect foreign key constraint name for models with quoted ``db_table`` (:ticket:`28876`). + +* Fixed a regression in caching of a ``GenericForeignKey`` when the referenced + model instance uses more than one level of multi-table inheritance + (:ticket:`28856`). diff --git a/tests/generic_relations_regress/models.py b/tests/generic_relations_regress/models.py index 669e7b7186..5f3b2f849c 100644 --- a/tests/generic_relations_regress/models.py +++ b/tests/generic_relations_regress/models.py @@ -43,6 +43,12 @@ class Restaurant(Place): @python_2_unicode_compatible +class Cafe(Restaurant): + def __str__(self): + return "Cafe: %s" % self.name + + +@python_2_unicode_compatible class Address(models.Model): street = models.CharField(max_length=80) city = models.CharField(max_length=50) diff --git a/tests/generic_relations_regress/tests.py b/tests/generic_relations_regress/tests.py index e6d350aa5b..adb26f6883 100644 --- a/tests/generic_relations_regress/tests.py +++ b/tests/generic_relations_regress/tests.py @@ -5,9 +5,10 @@ from django.forms.models import modelform_factory from django.test import TestCase, skipIfDBFeature from .models import ( - A, Address, B, Board, C, CharLink, Company, Contact, Content, D, Developer, - Guild, HasLinkThing, Link, Node, Note, OddRelation1, OddRelation2, - Organization, Person, Place, Related, Restaurant, Tag, Team, TextLink, + A, Address, B, Board, C, Cafe, CharLink, Company, Contact, Content, D, + Developer, Guild, HasLinkThing, Link, Node, Note, OddRelation1, + OddRelation2, Organization, Person, Place, Related, Restaurant, Tag, Team, + TextLink, ) @@ -53,6 +54,11 @@ class GenericRelationTests(TestCase): CharLink.objects.create(content_object=restaurant) charlink = CharLink.objects.latest('pk') self.assertIs(charlink.content_object, charlink.content_object) + # If the model (Cafe) uses more than one level of multi-table inheritance. + cafe = Cafe.objects.create() + CharLink.objects.create(content_object=cafe) + charlink = CharLink.objects.latest('pk') + self.assertIs(charlink.content_object, charlink.content_object) def test_q_object_or(self): """ |
