Fixed #18432 -- Prevented the ForeignKey field from creating an invalid query when chained. Thanks, Jann Kleen.
This commit is contained in:
parent
5e6ded2e58
commit
1a412dda62
|
@ -359,7 +359,7 @@ class ReverseSingleRelatedObjectDescriptor(object):
|
||||||
else:
|
else:
|
||||||
other_field = self.field.rel.get_related_field()
|
other_field = self.field.rel.get_related_field()
|
||||||
if other_field.rel:
|
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:
|
else:
|
||||||
params = {'%s__exact' % self.field.rel.field_name: val}
|
params = {'%s__exact' % self.field.rel.field_name: val}
|
||||||
qs = self.get_query_set(instance=instance)
|
qs = self.get_query_set(instance=instance)
|
||||||
|
|
|
@ -7,6 +7,7 @@ CHOICES = (
|
||||||
(2, 'second'),
|
(2, 'second'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Article(models.Model):
|
class Article(models.Model):
|
||||||
headline = models.CharField(max_length=100, default='Default headline')
|
headline = models.CharField(max_length=100, default='Default headline')
|
||||||
pub_date = models.DateTimeField()
|
pub_date = models.DateTimeField()
|
||||||
|
@ -15,24 +16,28 @@ class Article(models.Model):
|
||||||
article_text = models.TextField()
|
article_text = models.TextField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('pub_date','headline')
|
ordering = ('pub_date', 'headline')
|
||||||
# A utf-8 verbose name (Ångström's Articles) to test they are valid.
|
# A utf-8 verbose name (Ångström's Articles) to test they are valid.
|
||||||
verbose_name = "\xc3\x85ngstr\xc3\xb6m's Articles"
|
verbose_name = "\xc3\x85ngstr\xc3\xb6m's Articles"
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
|
|
||||||
class Movie(models.Model):
|
class Movie(models.Model):
|
||||||
#5218: Test models with non-default primary keys / AutoFields
|
#5218: Test models with non-default primary keys / AutoFields
|
||||||
movie_id = models.AutoField(primary_key=True)
|
movie_id = models.AutoField(primary_key=True)
|
||||||
name = models.CharField(max_length=60)
|
name = models.CharField(max_length=60)
|
||||||
|
|
||||||
|
|
||||||
class Party(models.Model):
|
class Party(models.Model):
|
||||||
when = models.DateField(null=True)
|
when = models.DateField(null=True)
|
||||||
|
|
||||||
|
|
||||||
class Event(models.Model):
|
class Event(models.Model):
|
||||||
when = models.DateTimeField()
|
when = models.DateTimeField()
|
||||||
|
|
||||||
|
|
||||||
class Department(models.Model):
|
class Department(models.Model):
|
||||||
id = models.PositiveIntegerField(primary_key=True)
|
id = models.PositiveIntegerField(primary_key=True)
|
||||||
name = models.CharField(max_length=200)
|
name = models.CharField(max_length=200)
|
||||||
|
@ -40,6 +45,7 @@ class Department(models.Model):
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class Worker(models.Model):
|
class Worker(models.Model):
|
||||||
department = models.ForeignKey(Department)
|
department = models.ForeignKey(Department)
|
||||||
name = models.CharField(max_length=200)
|
name = models.CharField(max_length=200)
|
||||||
|
@ -47,6 +53,7 @@ class Worker(models.Model):
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class BrokenUnicodeMethod(models.Model):
|
class BrokenUnicodeMethod(models.Model):
|
||||||
name = models.CharField(max_length=7)
|
name = models.CharField(max_length=7)
|
||||||
|
|
||||||
|
@ -55,5 +62,19 @@ class BrokenUnicodeMethod(models.Model):
|
||||||
# object).
|
# object).
|
||||||
return 'Názov: %s' % self.name
|
return 'Názov: %s' % self.name
|
||||||
|
|
||||||
|
|
||||||
class NonAutoPK(models.Model):
|
class NonAutoPK(models.Model):
|
||||||
name = models.CharField(max_length=10, primary_key=True)
|
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')
|
||||||
|
|
|
@ -8,8 +8,7 @@ from django.test import TestCase, skipUnlessDBFeature
|
||||||
from django.utils import tzinfo
|
from django.utils import tzinfo
|
||||||
|
|
||||||
from .models import (Worker, Article, Party, Event, Department,
|
from .models import (Worker, Article, Party, Event, Department,
|
||||||
BrokenUnicodeMethod, NonAutoPK)
|
BrokenUnicodeMethod, NonAutoPK, Model1, Model2, Model3)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ModelTests(TestCase):
|
class ModelTests(TestCase):
|
||||||
|
@ -47,7 +46,7 @@ class ModelTests(TestCase):
|
||||||
a = Article.objects.create(
|
a = Article.objects.create(
|
||||||
headline="Really, really big",
|
headline="Really, really big",
|
||||||
pub_date=datetime.datetime.now(),
|
pub_date=datetime.datetime.now(),
|
||||||
article_text = "ABCDE" * 1000
|
article_text="ABCDE" * 1000
|
||||||
)
|
)
|
||||||
a = Article.objects.get(pk=a.pk)
|
a = Article.objects.get(pk=a.pk)
|
||||||
self.assertEqual(len(a.article_text), 5000)
|
self.assertEqual(len(a.article_text), 5000)
|
||||||
|
@ -164,6 +163,19 @@ class ModelTests(TestCase):
|
||||||
1
|
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):
|
class ModelValidationTest(TestCase):
|
||||||
def test_pk_validation(self):
|
def test_pk_validation(self):
|
||||||
|
|
Loading…
Reference in New Issue