diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index c4cd1c4d83..96d1438282 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -359,7 +359,7 @@ class ReverseSingleRelatedObjectDescriptor(object): else: other_field = self.field.rel.get_related_field() if other_field.rel: - params = {'%s__pk' % self.field.rel.field_name: val} + params = {'%s__%s' % (self.field.rel.field_name, other_field.rel.field_name): val} else: params = {'%s__exact' % self.field.rel.field_name: val} qs = self.get_query_set(instance=instance) diff --git a/tests/regressiontests/model_regress/models.py b/tests/regressiontests/model_regress/models.py index f30b3eecd7..aca6d44837 100644 --- a/tests/regressiontests/model_regress/models.py +++ b/tests/regressiontests/model_regress/models.py @@ -7,6 +7,7 @@ CHOICES = ( (2, 'second'), ) + class Article(models.Model): headline = models.CharField(max_length=100, default='Default headline') pub_date = models.DateTimeField() @@ -15,24 +16,28 @@ class Article(models.Model): article_text = models.TextField() class Meta: - ordering = ('pub_date','headline') + ordering = ('pub_date', 'headline') # A utf-8 verbose name (Ångström's Articles) to test they are valid. verbose_name = "\xc3\x85ngstr\xc3\xb6m's Articles" def __unicode__(self): return self.headline + class Movie(models.Model): #5218: Test models with non-default primary keys / AutoFields movie_id = models.AutoField(primary_key=True) name = models.CharField(max_length=60) + class Party(models.Model): when = models.DateField(null=True) + class Event(models.Model): when = models.DateTimeField() + class Department(models.Model): id = models.PositiveIntegerField(primary_key=True) name = models.CharField(max_length=200) @@ -40,6 +45,7 @@ class Department(models.Model): def __unicode__(self): return self.name + class Worker(models.Model): department = models.ForeignKey(Department) name = models.CharField(max_length=200) @@ -47,6 +53,7 @@ class Worker(models.Model): def __unicode__(self): return self.name + class BrokenUnicodeMethod(models.Model): name = models.CharField(max_length=7) @@ -55,5 +62,19 @@ class BrokenUnicodeMethod(models.Model): # object). return 'Názov: %s' % self.name + class NonAutoPK(models.Model): name = models.CharField(max_length=10, primary_key=True) + + +#18432: Chained foreign keys with to_field produce incorrect query +class Model1(models.Model): + pkey = models.IntegerField(unique=True, db_index=True) + + +class Model2(models.Model): + model1 = models.ForeignKey(Model1, unique=True, to_field='pkey') + + +class Model3(models.Model): + model2 = models.ForeignKey(Model2, unique=True, to_field='model1') diff --git a/tests/regressiontests/model_regress/tests.py b/tests/regressiontests/model_regress/tests.py index 7ba9d421d7..7f9f514c7a 100644 --- a/tests/regressiontests/model_regress/tests.py +++ b/tests/regressiontests/model_regress/tests.py @@ -8,8 +8,7 @@ from django.test import TestCase, skipUnlessDBFeature from django.utils import tzinfo from .models import (Worker, Article, Party, Event, Department, - BrokenUnicodeMethod, NonAutoPK) - + BrokenUnicodeMethod, NonAutoPK, Model1, Model2, Model3) class ModelTests(TestCase): @@ -47,7 +46,7 @@ class ModelTests(TestCase): a = Article.objects.create( headline="Really, really big", pub_date=datetime.datetime.now(), - article_text = "ABCDE" * 1000 + article_text="ABCDE" * 1000 ) a = Article.objects.get(pk=a.pk) self.assertEqual(len(a.article_text), 5000) @@ -164,6 +163,19 @@ class ModelTests(TestCase): 1 ) + def test_chained_fks(self): + """ + Regression for #18432: Chained foreign keys with to_field produce incorrect query + """ + + m1 = Model1.objects.create(pkey=1000) + m2 = Model2.objects.create(model1=m1) + m3 = Model3.objects.create(model2=m2) + + # this is the actual test for #18432 + m3 = Model3.objects.get(model2=1000) + m3.model2 + class ModelValidationTest(TestCase): def test_pk_validation(self):