mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #34226 -- Fixed QuerySet.select_related() with multiple FilteredRelations to the OneToOneField.
This commit is contained in:
		@@ -1265,7 +1265,7 @@ class SQLCompiler:
 | 
				
			|||||||
                )
 | 
					                )
 | 
				
			||||||
                get_related_klass_infos(klass_info, next_klass_infos)
 | 
					                get_related_klass_infos(klass_info, next_klass_infos)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            def local_setter(obj, from_obj):
 | 
					            def local_setter(final_field, obj, from_obj):
 | 
				
			||||||
                # Set a reverse fk object when relation is non-empty.
 | 
					                # Set a reverse fk object when relation is non-empty.
 | 
				
			||||||
                if from_obj:
 | 
					                if from_obj:
 | 
				
			||||||
                    final_field.remote_field.set_cached_value(from_obj, obj)
 | 
					                    final_field.remote_field.set_cached_value(from_obj, obj)
 | 
				
			||||||
@@ -1291,7 +1291,7 @@ class SQLCompiler:
 | 
				
			|||||||
                        "model": model,
 | 
					                        "model": model,
 | 
				
			||||||
                        "field": final_field,
 | 
					                        "field": final_field,
 | 
				
			||||||
                        "reverse": True,
 | 
					                        "reverse": True,
 | 
				
			||||||
                        "local_setter": local_setter,
 | 
					                        "local_setter": partial(local_setter, final_field),
 | 
				
			||||||
                        "remote_setter": partial(remote_setter, name),
 | 
					                        "remote_setter": partial(remote_setter, name),
 | 
				
			||||||
                        "from_parent": from_parent,
 | 
					                        "from_parent": from_parent,
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,3 +24,6 @@ class Pool(models.Model):
 | 
				
			|||||||
class PoolStyle(models.Model):
 | 
					class PoolStyle(models.Model):
 | 
				
			||||||
    name = models.CharField(max_length=30)
 | 
					    name = models.CharField(max_length=30)
 | 
				
			||||||
    pool = models.OneToOneField(Pool, models.CASCADE)
 | 
					    pool = models.OneToOneField(Pool, models.CASCADE)
 | 
				
			||||||
 | 
					    another_pool = models.OneToOneField(
 | 
				
			||||||
 | 
					        Pool, models.CASCADE, null=True, related_name="another_style"
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					from django.db.models import FilteredRelation
 | 
				
			||||||
from django.test import TestCase
 | 
					from django.test import TestCase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .models import Organiser, Pool, PoolStyle, Tournament
 | 
					from .models import Organiser, Pool, PoolStyle, Tournament
 | 
				
			||||||
@@ -23,6 +24,9 @@ class ExistingRelatedInstancesTests(TestCase):
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
        cls.ps1 = PoolStyle.objects.create(name="T1 Pool 2 Style", pool=cls.p2)
 | 
					        cls.ps1 = PoolStyle.objects.create(name="T1 Pool 2 Style", pool=cls.p2)
 | 
				
			||||||
        cls.ps2 = PoolStyle.objects.create(name="T2 Pool 1 Style", pool=cls.p3)
 | 
					        cls.ps2 = PoolStyle.objects.create(name="T2 Pool 1 Style", pool=cls.p3)
 | 
				
			||||||
 | 
					        cls.ps3 = PoolStyle.objects.create(
 | 
				
			||||||
 | 
					            name="T1 Pool 1/3 Style", pool=cls.p1, another_pool=cls.p3
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_foreign_key(self):
 | 
					    def test_foreign_key(self):
 | 
				
			||||||
        with self.assertNumQueries(2):
 | 
					        with self.assertNumQueries(2):
 | 
				
			||||||
@@ -147,3 +151,16 @@ class ExistingRelatedInstancesTests(TestCase):
 | 
				
			|||||||
            pools = list(Pool.objects.prefetch_related("poolstyle").order_by("pk"))
 | 
					            pools = list(Pool.objects.prefetch_related("poolstyle").order_by("pk"))
 | 
				
			||||||
            self.assertIs(pools[1], pools[1].poolstyle.pool)
 | 
					            self.assertIs(pools[1], pools[1].poolstyle.pool)
 | 
				
			||||||
            self.assertIs(pools[2], pools[2].poolstyle.pool)
 | 
					            self.assertIs(pools[2], pools[2].poolstyle.pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_reverse_fk_select_related_multiple(self):
 | 
				
			||||||
 | 
					        with self.assertNumQueries(1):
 | 
				
			||||||
 | 
					            ps = list(
 | 
				
			||||||
 | 
					                PoolStyle.objects.annotate(
 | 
				
			||||||
 | 
					                    pool_1=FilteredRelation("pool"),
 | 
				
			||||||
 | 
					                    pool_2=FilteredRelation("another_pool"),
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					                .select_related("pool_1", "pool_2")
 | 
				
			||||||
 | 
					                .order_by("-pk")
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            self.assertIs(ps[0], ps[0].pool_1.poolstyle)
 | 
				
			||||||
 | 
					            self.assertIs(ps[0], ps[0].pool_2.another_style)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user