summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMorgan Wahl <morgan@addgene.org>2017-12-05 16:08:50 -0500
committerMorgan Wahl <morgan@addgene.org>2017-12-07 09:34:54 -0500
commit35222035029863f95769e2e59beeeb953d125689 (patch)
treec4a9537b79c35340271e01e6de1463d6ed0983f7
parent1decd0197d241b27d54bb12eca04b7e89a9ccba6 (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.py10
-rw-r--r--docs/releases/1.11.9.txt4
-rw-r--r--tests/generic_relations_regress/models.py6
-rw-r--r--tests/generic_relations_regress/tests.py12
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):
"""