summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMorgan Wahl <morgan@addgene.org>2017-12-05 16:08:50 -0500
committerTim Graham <timograham@gmail.com>2017-12-08 14:00:50 -0500
commit5ca9cf47a7adcb990bd7e4886d5b8c066b5ca171 (patch)
tree02d8487a9b241c7979985b968f5ebc251a9674e9
parent6dea1b18f3ef0f4a2538114b151119f00be1a1e7 (diff)
[2.0.x] Refs #28856 -- Fixed caching of a GenericForeignKey pointing to a model that uses more than one level of MTI.
Forwardport of 35222035029863f95769e2e59beeeb953d125689 from stable/1.11.x
-rw-r--r--django/contrib/contenttypes/fields.py10
-rw-r--r--docs/releases/1.11.9.txt4
-rw-r--r--docs/releases/2.0.1.txt4
-rw-r--r--tests/generic_relations_regress/models.py5
-rw-r--r--tests/generic_relations_regress/tests.py12
5 files changed, 31 insertions, 4 deletions
diff --git a/django/contrib/contenttypes/fields.py b/django/contrib/contenttypes/fields.py
index 42e06aa119..9b86e9d1aa 100644
--- a/django/contrib/contenttypes/fields.py
+++ b/django/contrib/contenttypes/fields.py
@@ -234,7 +234,15 @@ class GenericForeignKey(FieldCacheMixin):
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
else:
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/docs/releases/2.0.1.txt b/docs/releases/2.0.1.txt
index 67bdc1b9a0..9c111a1674 100644
--- a/docs/releases/2.0.1.txt
+++ b/docs/releases/2.0.1.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 2011ea14b9..c9572eb961 100644
--- a/tests/generic_relations_regress/models.py
+++ b/tests/generic_relations_regress/models.py
@@ -38,6 +38,11 @@ class Restaurant(Place):
return "Restaurant: %s" % self.name
+class Cafe(Restaurant):
+ def __str__(self):
+ return "Cafe: %s" % self.name
+
+
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 cfac484053..91158d8198 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):
"""