summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordarius BERNARD <darius.bernard@onysos.fr>2016-04-18 14:59:01 +0200
committerTim Graham <timograham@gmail.com>2016-05-19 09:56:24 -0400
commita7ad473ad27995736b07750ac64e2651ff790529 (patch)
tree89dd5c74ab8ced3a87e5d274ace58445f237a6fe
parent2e1d44e46d1ea3d8c9fdc5c323a127f51006f6c3 (diff)
downloaddjango-a7ad473ad27995736b07750ac64e2651ff790529.tar.gz
Fixed #26515 -- Fixed Query.trim_joins() for nested ForeignObjects.
-rw-r--r--django/db/models/sql/query.py3
-rw-r--r--tests/foreign_object/models/__init__.py6
-rw-r--r--tests/foreign_object/models/customers.py38
-rw-r--r--tests/foreign_object/test_agnostic_order_trimjoin.py28
4 files changed, 72 insertions, 3 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 6946c273c7..d182242ce4 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -1438,7 +1438,8 @@ class Query(object):
cur_targets = set(t.column for t in targets)
if not cur_targets.issubset(join_targets):
break
- targets = tuple(r[0] for r in info.join_field.related_fields if r[1].column in cur_targets)
+ targets_dict = {r[1].column: r[0] for r in info.join_field.related_fields if r[1].column in cur_targets}
+ targets = tuple(targets_dict[t.column] for t in targets)
self.unref_alias(joins.pop())
return targets, joins[-1], joins
diff --git a/tests/foreign_object/models/__init__.py b/tests/foreign_object/models/__init__.py
index 8fe4ff10df..652a2a30a1 100644
--- a/tests/foreign_object/models/__init__.py
+++ b/tests/foreign_object/models/__init__.py
@@ -1,10 +1,12 @@
from .article import (
Article, ArticleIdea, ArticleTag, ArticleTranslation, NewsArticle,
)
+from .customers import Address, Contact, Customer
from .empty_join import SlugPage
from .person import Country, Friendship, Group, Membership, Person
__all__ = [
- 'Article', 'ArticleIdea', 'ArticleTag', 'ArticleTranslation', 'Country',
- 'Friendship', 'Group', 'Membership', 'NewsArticle', 'Person', 'SlugPage',
+ 'Address', 'Article', 'ArticleIdea', 'ArticleTag', 'ArticleTranslation',
+ 'Contact', 'Country', 'Customer', 'Friendship', 'Group', 'Membership',
+ 'NewsArticle', 'Person', 'SlugPage',
]
diff --git a/tests/foreign_object/models/customers.py b/tests/foreign_object/models/customers.py
new file mode 100644
index 0000000000..24c080f407
--- /dev/null
+++ b/tests/foreign_object/models/customers.py
@@ -0,0 +1,38 @@
+from django.db import models
+from django.db.models.fields.related import ForeignObject
+
+
+class Address(models.Model):
+ company = models.CharField(max_length=1)
+ customer_id = models.IntegerField()
+
+ class Meta:
+ unique_together = [
+ ('company', 'customer_id'),
+ ]
+
+
+class Customer(models.Model):
+ company = models.CharField(max_length=1)
+ customer_id = models.IntegerField()
+ address = ForeignObject(
+ Address, models.CASCADE, null=True,
+ # order mismatches the Contact ForeignObject.
+ from_fields=['company', 'customer_id'],
+ to_fields=['company', 'customer_id'],
+ )
+
+ class Meta:
+ unique_together = [
+ ('company', 'customer_id'),
+ ]
+
+
+class Contact(models.Model):
+ company_code = models.CharField(max_length=1)
+ customer_code = models.IntegerField()
+ customer = ForeignObject(
+ Customer, models.CASCADE, related_name='contacts',
+ to_fields=['customer_id', 'company'],
+ from_fields=['customer_code', 'company_code'],
+ )
diff --git a/tests/foreign_object/test_agnostic_order_trimjoin.py b/tests/foreign_object/test_agnostic_order_trimjoin.py
new file mode 100644
index 0000000000..d3b7184be6
--- /dev/null
+++ b/tests/foreign_object/test_agnostic_order_trimjoin.py
@@ -0,0 +1,28 @@
+from operator import attrgetter
+
+from django.test.testcases import TestCase
+
+from .models import Address, Contact, Customer
+
+
+class TestLookupQuery(TestCase):
+
+ @classmethod
+ def setUpTestData(cls):
+ cls.address = Address.objects.create(company=1, customer_id=20)
+ cls.customer1 = Customer.objects.create(company=1, customer_id=20)
+ cls.contact1 = Contact.objects.create(company_code=1, customer_code=20)
+
+ def test_deep_mixed_forward(self):
+ self.assertQuerysetEqual(
+ Address.objects.filter(customer__contacts=self.contact1),
+ [self.address.id],
+ attrgetter('id')
+ )
+
+ def test_deep_mixed_backward(self):
+ self.assertQuerysetEqual(
+ Contact.objects.filter(customer__address=self.address),
+ [self.contact1.id],
+ attrgetter('id')
+ )