mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			187 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			187 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from django.db.models import FilteredRelation
 | |
| from django.test import TestCase
 | |
| 
 | |
| from .models import Organiser, Pool, PoolStyle, Tournament
 | |
| 
 | |
| 
 | |
| class ExistingRelatedInstancesTests(TestCase):
 | |
|     @classmethod
 | |
|     def setUpTestData(cls):
 | |
|         cls.t1 = Tournament.objects.create(name="Tourney 1")
 | |
|         cls.t2 = Tournament.objects.create(name="Tourney 2")
 | |
|         cls.o1 = Organiser.objects.create(name="Organiser 1")
 | |
|         cls.p1 = Pool.objects.create(
 | |
|             name="T1 Pool 1", tournament=cls.t1, organiser=cls.o1
 | |
|         )
 | |
|         cls.p2 = Pool.objects.create(
 | |
|             name="T1 Pool 2", tournament=cls.t1, organiser=cls.o1
 | |
|         )
 | |
|         cls.p3 = Pool.objects.create(
 | |
|             name="T2 Pool 1", tournament=cls.t2, organiser=cls.o1
 | |
|         )
 | |
|         cls.p4 = Pool.objects.create(
 | |
|             name="T2 Pool 2", tournament=cls.t2, organiser=cls.o1
 | |
|         )
 | |
|         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.ps3 = PoolStyle.objects.create(
 | |
|             name="T1 Pool 1/3 Style", pool=cls.p1, another_pool=cls.p3
 | |
|         )
 | |
| 
 | |
|     def test_foreign_key(self):
 | |
|         with self.assertNumQueries(2):
 | |
|             tournament = Tournament.objects.get(pk=self.t1.pk)
 | |
|             pool = tournament.pool_set.all()[0]
 | |
|             self.assertIs(tournament, pool.tournament)
 | |
| 
 | |
|     def test_foreign_key_prefetch_related(self):
 | |
|         with self.assertNumQueries(2):
 | |
|             tournament = Tournament.objects.prefetch_related("pool_set").get(
 | |
|                 pk=self.t1.pk
 | |
|             )
 | |
|             pool = tournament.pool_set.all()[0]
 | |
|             self.assertIs(tournament, pool.tournament)
 | |
| 
 | |
|     def test_foreign_key_multiple_prefetch(self):
 | |
|         with self.assertNumQueries(2):
 | |
|             tournaments = list(
 | |
|                 Tournament.objects.prefetch_related("pool_set").order_by("pk")
 | |
|             )
 | |
|             pool1 = tournaments[0].pool_set.all()[0]
 | |
|             self.assertIs(tournaments[0], pool1.tournament)
 | |
|             pool2 = tournaments[1].pool_set.all()[0]
 | |
|             self.assertIs(tournaments[1], pool2.tournament)
 | |
| 
 | |
|     def test_queryset_or(self):
 | |
|         tournament_1 = self.t1
 | |
|         tournament_2 = self.t2
 | |
|         with self.assertNumQueries(1):
 | |
|             pools = tournament_1.pool_set.all() | tournament_2.pool_set.all()
 | |
|             related_objects = {pool.tournament for pool in pools}
 | |
|             self.assertEqual(related_objects, {tournament_1, tournament_2})
 | |
| 
 | |
|     def test_queryset_or_different_cached_items(self):
 | |
|         tournament = self.t1
 | |
|         organiser = self.o1
 | |
|         with self.assertNumQueries(1):
 | |
|             pools = tournament.pool_set.all() | organiser.pool_set.all()
 | |
|             first = pools.filter(pk=self.p1.pk)[0]
 | |
|             self.assertIs(first.tournament, tournament)
 | |
|             self.assertIs(first.organiser, organiser)
 | |
| 
 | |
|     def test_queryset_or_only_one_with_precache(self):
 | |
|         tournament_1 = self.t1
 | |
|         tournament_2 = self.t2
 | |
|         # 2 queries here as pool 3 has tournament 2, which is not cached
 | |
|         with self.assertNumQueries(2):
 | |
|             pools = tournament_1.pool_set.all() | Pool.objects.filter(pk=self.p3.pk)
 | |
|             related_objects = {pool.tournament for pool in pools}
 | |
|             self.assertEqual(related_objects, {tournament_1, tournament_2})
 | |
|         # and the other direction
 | |
|         with self.assertNumQueries(2):
 | |
|             pools = Pool.objects.filter(pk=self.p3.pk) | tournament_1.pool_set.all()
 | |
|             related_objects = {pool.tournament for pool in pools}
 | |
|             self.assertEqual(related_objects, {tournament_1, tournament_2})
 | |
| 
 | |
|     def test_queryset_and(self):
 | |
|         tournament = self.t1
 | |
|         organiser = self.o1
 | |
|         with self.assertNumQueries(1):
 | |
|             pools = tournament.pool_set.all() & organiser.pool_set.all()
 | |
|             first = pools.filter(pk=self.p1.pk)[0]
 | |
|             self.assertIs(first.tournament, tournament)
 | |
|             self.assertIs(first.organiser, organiser)
 | |
| 
 | |
|     def test_one_to_one(self):
 | |
|         with self.assertNumQueries(2):
 | |
|             style = PoolStyle.objects.get(pk=self.ps1.pk)
 | |
|             pool = style.pool
 | |
|             self.assertIs(style, pool.poolstyle)
 | |
| 
 | |
|     def test_one_to_one_select_related(self):
 | |
|         with self.assertNumQueries(1):
 | |
|             style = PoolStyle.objects.select_related("pool").get(pk=self.ps1.pk)
 | |
|             pool = style.pool
 | |
|             self.assertIs(style, pool.poolstyle)
 | |
| 
 | |
|     def test_one_to_one_multi_select_related(self):
 | |
|         with self.assertNumQueries(1):
 | |
|             poolstyles = list(PoolStyle.objects.select_related("pool").order_by("pk"))
 | |
|             self.assertIs(poolstyles[0], poolstyles[0].pool.poolstyle)
 | |
|             self.assertIs(poolstyles[1], poolstyles[1].pool.poolstyle)
 | |
| 
 | |
|     def test_one_to_one_prefetch_related(self):
 | |
|         with self.assertNumQueries(2):
 | |
|             style = PoolStyle.objects.prefetch_related("pool").get(pk=self.ps1.pk)
 | |
|             pool = style.pool
 | |
|             self.assertIs(style, pool.poolstyle)
 | |
| 
 | |
|     def test_one_to_one_multi_prefetch_related(self):
 | |
|         with self.assertNumQueries(2):
 | |
|             poolstyles = list(PoolStyle.objects.prefetch_related("pool").order_by("pk"))
 | |
|             self.assertIs(poolstyles[0], poolstyles[0].pool.poolstyle)
 | |
|             self.assertIs(poolstyles[1], poolstyles[1].pool.poolstyle)
 | |
| 
 | |
|     def test_reverse_one_to_one(self):
 | |
|         with self.assertNumQueries(2):
 | |
|             pool = Pool.objects.get(pk=self.p2.pk)
 | |
|             style = pool.poolstyle
 | |
|             self.assertIs(pool, style.pool)
 | |
| 
 | |
|     def test_reverse_one_to_one_select_related(self):
 | |
|         with self.assertNumQueries(1):
 | |
|             pool = Pool.objects.select_related("poolstyle").get(pk=self.p2.pk)
 | |
|             style = pool.poolstyle
 | |
|             self.assertIs(pool, style.pool)
 | |
| 
 | |
|     def test_reverse_one_to_one_prefetch_related(self):
 | |
|         with self.assertNumQueries(2):
 | |
|             pool = Pool.objects.prefetch_related("poolstyle").get(pk=self.p2.pk)
 | |
|             style = pool.poolstyle
 | |
|             self.assertIs(pool, style.pool)
 | |
| 
 | |
|     def test_reverse_one_to_one_multi_select_related(self):
 | |
|         with self.assertNumQueries(1):
 | |
|             pools = list(Pool.objects.select_related("poolstyle").order_by("pk"))
 | |
|             self.assertIs(pools[1], pools[1].poolstyle.pool)
 | |
|             self.assertIs(pools[2], pools[2].poolstyle.pool)
 | |
| 
 | |
|     def test_reverse_one_to_one_multi_prefetch_related(self):
 | |
|         with self.assertNumQueries(2):
 | |
|             pools = list(Pool.objects.prefetch_related("poolstyle").order_by("pk"))
 | |
|             self.assertIs(pools[1], pools[1].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)
 | |
| 
 | |
|     def test_multilevel_reverse_fk_cyclic_select_related(self):
 | |
|         with self.assertNumQueries(3):
 | |
|             p = list(
 | |
|                 PoolStyle.objects.annotate(
 | |
|                     tournament_pool=FilteredRelation("pool__tournament__pool"),
 | |
|                 ).select_related("tournament_pool", "tournament_pool__tournament")
 | |
|             )
 | |
|             self.assertEqual(p[0].tournament_pool.tournament, p[0].pool.tournament)
 | |
| 
 | |
|     def test_multilevel_reverse_fk_select_related(self):
 | |
|         with self.assertNumQueries(2):
 | |
|             p = list(
 | |
|                 Tournament.objects.filter(id=self.t2.id)
 | |
|                 .annotate(
 | |
|                     style=FilteredRelation("pool__another_style"),
 | |
|                 )
 | |
|                 .select_related("style")
 | |
|             )
 | |
|             self.assertEqual(p[0].style.another_pool, self.p3)
 |