From 4a9f9cc521f09c60f56024eb6688e30ab86b998f Mon Sep 17 00:00:00 2001 From: Daniel Hillier Date: Wed, 14 Dec 2016 01:06:54 +1100 Subject: [PATCH] Fixed #27594 -- Fixed select_related() with reverse self-referential OneToOneField. Fix definition of `klass_info['from_parent']`. The relationship between two models shouldn't be considered as being from a parent class if the model classes are the same. Thanks Tim for the review. --- django/db/models/sql/compiler.py | 2 +- tests/select_related_onetoone/models.py | 9 +++++++++ tests/select_related_onetoone/tests.py | 12 ++++++++++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py index fed4353a3a..579e289c72 100644 --- a/django/db/models/sql/compiler.py +++ b/django/db/models/sql/compiler.py @@ -724,7 +724,7 @@ class SQLCompiler(object): _, _, _, joins, _ = self.query.setup_joins([related_field_name], opts, root_alias) alias = joins[-1] - from_parent = issubclass(model, opts.model) + from_parent = issubclass(model, opts.model) and model is not opts.model klass_info = { 'model': model, 'field': f, diff --git a/tests/select_related_onetoone/models.py b/tests/select_related_onetoone/models.py index 9af1b3f31b..773ae65125 100644 --- a/tests/select_related_onetoone/models.py +++ b/tests/select_related_onetoone/models.py @@ -102,3 +102,12 @@ class Child3(Child2): class Child4(Child1): value4 = models.IntegerField() + + +class LinkedList(models.Model): + name = models.CharField(max_length=50) + previous_item = models.OneToOneField( + 'self', models.CASCADE, + related_name="next_item", blank=True, + null=True, + ) diff --git a/tests/select_related_onetoone/tests.py b/tests/select_related_onetoone/tests.py index 2cb17a5ba9..81b6d0e8f4 100644 --- a/tests/select_related_onetoone/tests.py +++ b/tests/select_related_onetoone/tests.py @@ -6,8 +6,9 @@ from django.core.exceptions import FieldError from django.test import TestCase from .models import ( - AdvancedUserStat, Child1, Child2, Child3, Child4, Image, Parent1, Parent2, - Product, StatDetails, User, UserProfile, UserStat, UserStatResult, + AdvancedUserStat, Child1, Child2, Child3, Child4, Image, LinkedList, + Parent1, Parent2, Product, StatDetails, User, UserProfile, UserStat, + UserStatResult, ) @@ -212,6 +213,13 @@ class ReverseSelectRelatedTestCase(TestCase): with self.assertNumQueries(1): self.assertEqual(p.child1.child4.name1, 'n1') + def test_self_relation(self): + item1 = LinkedList.objects.create(name='item1') + LinkedList.objects.create(name='item2', previous_item=item1) + with self.assertNumQueries(1): + item1_db = LinkedList.objects.select_related('next_item').get(name='item1') + self.assertEqual(item1_db.next_item.name, 'item2') + class ReverseSelectRelatedValidationTests(TestCase): """