Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixed #18177 -- Cached known related instances.
This was recently fixed for one-to-one relations; this patch adds support for foreign keys. Thanks kaiser.yann for the report and the initial version of the patch.
- Loading branch information
Showing
7 changed files
with
243 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
65 changes: 65 additions & 0 deletions
65
tests/modeltests/known_related_objects/fixtures/tournament.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
[ | ||
{ | ||
"pk": 1, | ||
"model": "known_related_objects.tournament", | ||
"fields": { | ||
"name": "Tourney 1" | ||
} | ||
}, | ||
{ | ||
"pk": 2, | ||
"model": "known_related_objects.tournament", | ||
"fields": { | ||
"name": "Tourney 2" | ||
} | ||
}, | ||
{ | ||
"pk": 1, | ||
"model": "known_related_objects.pool", | ||
"fields": { | ||
"tournament": 1, | ||
"name": "T1 Pool 1" | ||
} | ||
}, | ||
{ | ||
"pk": 2, | ||
"model": "known_related_objects.pool", | ||
"fields": { | ||
"tournament": 1, | ||
"name": "T1 Pool 2" | ||
} | ||
}, | ||
{ | ||
"pk": 3, | ||
"model": "known_related_objects.pool", | ||
"fields": { | ||
"tournament": 2, | ||
"name": "T2 Pool 1" | ||
} | ||
}, | ||
{ | ||
"pk": 4, | ||
"model": "known_related_objects.pool", | ||
"fields": { | ||
"tournament": 2, | ||
"name": "T2 Pool 2" | ||
} | ||
}, | ||
{ | ||
"pk": 1, | ||
"model": "known_related_objects.poolstyle", | ||
"fields": { | ||
"name": "T1 Pool 2 Style", | ||
"pool": 2 | ||
} | ||
}, | ||
{ | ||
"pk": 2, | ||
"model": "known_related_objects.poolstyle", | ||
"fields": { | ||
"name": "T2 Pool 1 Style", | ||
"pool": 3 | ||
} | ||
} | ||
] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
""" | ||
Existing related object instance caching. | ||
Test that queries are not redone when going back through known relations. | ||
""" | ||
|
||
from django.db import models | ||
|
||
class Tournament(models.Model): | ||
name = models.CharField(max_length=30) | ||
|
||
class Pool(models.Model): | ||
name = models.CharField(max_length=30) | ||
tournament = models.ForeignKey(Tournament) | ||
|
||
class PoolStyle(models.Model): | ||
name = models.CharField(max_length=30) | ||
pool = models.OneToOneField(Pool) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
from __future__ import absolute_import | ||
|
||
from django.test import TestCase | ||
|
||
from .models import Tournament, Pool, PoolStyle | ||
|
||
class ExistingRelatedInstancesTests(TestCase): | ||
fixtures = ['tournament.json'] | ||
|
||
def test_foreign_key(self): | ||
with self.assertNumQueries(2): | ||
tournament = Tournament.objects.get(pk=1) | ||
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=1)) | ||
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')) | ||
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_one_to_one(self): | ||
with self.assertNumQueries(2): | ||
style = PoolStyle.objects.get(pk=1) | ||
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=1) | ||
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')) | ||
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=1) | ||
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')) | ||
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=2) | ||
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=2) | ||
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=2) | ||
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')) | ||
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')) | ||
self.assertIs(pools[1], pools[1].poolstyle.pool) | ||
self.assertIs(pools[2], pools[2].poolstyle.pool) |