~ubuntuone-pqm-team/django/stable

« back to all changes in this revision

Viewing changes to tests/nested_foreign_keys/tests.py

  • Committer: Matias Bordese
  • Date: 2014-08-21 21:22:40 UTC
  • Revision ID: matias.bordese@canonical.com-20140821212240-tij4ms6qzjbdiioz
Tags: 1.5.9
Imported Django 1.5.9 from released tarball.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
from __future__ import absolute_import
2
 
from django.test import TestCase
3
 
 
4
 
from .models import Person, Movie, Event, Screening, ScreeningNullFK, Package, PackageNullFK
5
 
 
6
 
 
7
 
# These are tests for #16715. The basic scheme is always the same: 3 models with
8
 
# 2 relations. The first relation may be null, while the second is non-nullable.
9
 
# In some cases, Django would pick the wrong join type for the second relation,
10
 
# resulting in missing objects in the queryset.
11
 
#
12
 
#   Model A
13
 
#   | (Relation A/B : nullable)
14
 
#   Model B
15
 
#   | (Relation B/C : non-nullable)
16
 
#   Model C
17
 
#
18
 
# Because of the possibility of NULL rows resulting from the LEFT OUTER JOIN
19
 
# between Model A and Model B (i.e. instances of A without reference to B),
20
 
# the second join must also be LEFT OUTER JOIN, so that we do not ignore
21
 
# instances of A that do not reference B.
22
 
#
23
 
# Relation A/B can either be an explicit foreign key or an implicit reverse
24
 
# relation such as introduced by one-to-one relations (through multi-table
25
 
# inheritance).
26
 
class NestedForeignKeysTests(TestCase):
27
 
    def setUp(self):
28
 
        self.director = Person.objects.create(name='Terry Gilliam / Terry Jones')
29
 
        self.movie = Movie.objects.create(title='Monty Python and the Holy Grail', director=self.director)
30
 
 
31
 
 
32
 
    # This test failed in #16715 because in some cases INNER JOIN was selected
33
 
    # for the second foreign key relation instead of LEFT OUTER JOIN.
34
 
    def testInheritance(self):
35
 
        some_event = Event.objects.create()
36
 
        screening = Screening.objects.create(movie=self.movie)
37
 
 
38
 
        self.assertEqual(len(Event.objects.all()), 2)
39
 
        self.assertEqual(len(Event.objects.select_related('screening')), 2)
40
 
        # This failed.
41
 
        self.assertEqual(len(Event.objects.select_related('screening__movie')), 2)
42
 
 
43
 
        self.assertEqual(len(Event.objects.values()), 2)
44
 
        self.assertEqual(len(Event.objects.values('screening__pk')), 2)
45
 
        self.assertEqual(len(Event.objects.values('screening__movie__pk')), 2)
46
 
        self.assertEqual(len(Event.objects.values('screening__movie__title')), 2)
47
 
        # This failed.
48
 
        self.assertEqual(len(Event.objects.values('screening__movie__pk', 'screening__movie__title')), 2)
49
 
 
50
 
        # Simple filter/exclude queries for good measure.
51
 
        self.assertEqual(Event.objects.filter(screening__movie=self.movie).count(), 1)
52
 
        self.assertEqual(Event.objects.exclude(screening__movie=self.movie).count(), 1)
53
 
 
54
 
 
55
 
    # These all work because the second foreign key in the chain has null=True.
56
 
    def testInheritanceNullFK(self):
57
 
        some_event = Event.objects.create()
58
 
        screening = ScreeningNullFK.objects.create(movie=None)
59
 
        screening_with_movie = ScreeningNullFK.objects.create(movie=self.movie)
60
 
 
61
 
        self.assertEqual(len(Event.objects.all()), 3)
62
 
        self.assertEqual(len(Event.objects.select_related('screeningnullfk')), 3)
63
 
        self.assertEqual(len(Event.objects.select_related('screeningnullfk__movie')), 3)
64
 
 
65
 
        self.assertEqual(len(Event.objects.values()), 3)
66
 
        self.assertEqual(len(Event.objects.values('screeningnullfk__pk')), 3)
67
 
        self.assertEqual(len(Event.objects.values('screeningnullfk__movie__pk')), 3)
68
 
        self.assertEqual(len(Event.objects.values('screeningnullfk__movie__title')), 3)
69
 
        self.assertEqual(len(Event.objects.values('screeningnullfk__movie__pk', 'screeningnullfk__movie__title')), 3)
70
 
 
71
 
        self.assertEqual(Event.objects.filter(screeningnullfk__movie=self.movie).count(), 1)
72
 
        self.assertEqual(Event.objects.exclude(screeningnullfk__movie=self.movie).count(), 2)
73
 
 
74
 
    def test_null_exclude(self):
75
 
        screening = ScreeningNullFK.objects.create(movie=None)
76
 
        ScreeningNullFK.objects.create(movie=self.movie)
77
 
        self.assertEqual(
78
 
            list(ScreeningNullFK.objects.exclude(movie__id=self.movie.pk)),
79
 
            [screening])
80
 
 
81
 
    # This test failed in #16715 because in some cases INNER JOIN was selected
82
 
    # for the second foreign key relation instead of LEFT OUTER JOIN.
83
 
    def testExplicitForeignKey(self):
84
 
        package = Package.objects.create()
85
 
        screening = Screening.objects.create(movie=self.movie)
86
 
        package_with_screening = Package.objects.create(screening=screening)
87
 
 
88
 
        self.assertEqual(len(Package.objects.all()), 2)
89
 
        self.assertEqual(len(Package.objects.select_related('screening')), 2)
90
 
        self.assertEqual(len(Package.objects.select_related('screening__movie')), 2)
91
 
 
92
 
        self.assertEqual(len(Package.objects.values()), 2)
93
 
        self.assertEqual(len(Package.objects.values('screening__pk')), 2)
94
 
        self.assertEqual(len(Package.objects.values('screening__movie__pk')), 2)
95
 
        self.assertEqual(len(Package.objects.values('screening__movie__title')), 2)
96
 
        # This failed.
97
 
        self.assertEqual(len(Package.objects.values('screening__movie__pk', 'screening__movie__title')), 2)
98
 
 
99
 
        self.assertEqual(Package.objects.filter(screening__movie=self.movie).count(), 1)
100
 
        self.assertEqual(Package.objects.exclude(screening__movie=self.movie).count(), 1)
101
 
 
102
 
 
103
 
    # These all work because the second foreign key in the chain has null=True.
104
 
    def testExplicitForeignKeyNullFK(self):
105
 
        package = PackageNullFK.objects.create()
106
 
        screening = ScreeningNullFK.objects.create(movie=None)
107
 
        screening_with_movie = ScreeningNullFK.objects.create(movie=self.movie)
108
 
        package_with_screening = PackageNullFK.objects.create(screening=screening)
109
 
        package_with_screening_with_movie = PackageNullFK.objects.create(screening=screening_with_movie)
110
 
 
111
 
        self.assertEqual(len(PackageNullFK.objects.all()), 3)
112
 
        self.assertEqual(len(PackageNullFK.objects.select_related('screening')), 3)
113
 
        self.assertEqual(len(PackageNullFK.objects.select_related('screening__movie')), 3)
114
 
 
115
 
        self.assertEqual(len(PackageNullFK.objects.values()), 3)
116
 
        self.assertEqual(len(PackageNullFK.objects.values('screening__pk')), 3)
117
 
        self.assertEqual(len(PackageNullFK.objects.values('screening__movie__pk')), 3)
118
 
        self.assertEqual(len(PackageNullFK.objects.values('screening__movie__title')), 3)
119
 
        self.assertEqual(len(PackageNullFK.objects.values('screening__movie__pk', 'screening__movie__title')), 3)
120
 
 
121
 
        self.assertEqual(PackageNullFK.objects.filter(screening__movie=self.movie).count(), 1)
122
 
        self.assertEqual(PackageNullFK.objects.exclude(screening__movie=self.movie).count(), 2)
123
 
 
124
 
 
125
 
# Some additional tests for #16715. The only difference is the depth of the
126
 
# nesting as we now use 4 models instead of 3 (and thus 3 relations). This
127
 
# checks if promotion of join types works for deeper nesting too.
128
 
class DeeplyNestedForeignKeysTests(TestCase):
129
 
    def setUp(self):
130
 
        self.director = Person.objects.create(name='Terry Gilliam / Terry Jones')
131
 
        self.movie = Movie.objects.create(title='Monty Python and the Holy Grail', director=self.director)
132
 
 
133
 
 
134
 
    def testInheritance(self):
135
 
        some_event = Event.objects.create()
136
 
        screening = Screening.objects.create(movie=self.movie)
137
 
 
138
 
        self.assertEqual(len(Event.objects.all()), 2)
139
 
        self.assertEqual(len(Event.objects.select_related('screening__movie__director')), 2)
140
 
 
141
 
        self.assertEqual(len(Event.objects.values()), 2)
142
 
        self.assertEqual(len(Event.objects.values('screening__movie__director__pk')), 2)
143
 
        self.assertEqual(len(Event.objects.values('screening__movie__director__name')), 2)
144
 
        self.assertEqual(len(Event.objects.values('screening__movie__director__pk', 'screening__movie__director__name')), 2)
145
 
        self.assertEqual(len(Event.objects.values('screening__movie__pk', 'screening__movie__director__pk')), 2)
146
 
        self.assertEqual(len(Event.objects.values('screening__movie__pk', 'screening__movie__director__name')), 2)
147
 
        self.assertEqual(len(Event.objects.values('screening__movie__title', 'screening__movie__director__pk')), 2)
148
 
        self.assertEqual(len(Event.objects.values('screening__movie__title', 'screening__movie__director__name')), 2)
149
 
 
150
 
        self.assertEqual(Event.objects.filter(screening__movie__director=self.director).count(), 1)
151
 
        self.assertEqual(Event.objects.exclude(screening__movie__director=self.director).count(), 1)
152
 
 
153
 
 
154
 
    def testExplicitForeignKey(self):
155
 
        package = Package.objects.create()
156
 
        screening = Screening.objects.create(movie=self.movie)
157
 
        package_with_screening = Package.objects.create(screening=screening)
158
 
 
159
 
        self.assertEqual(len(Package.objects.all()), 2)
160
 
        self.assertEqual(len(Package.objects.select_related('screening__movie__director')), 2)
161
 
 
162
 
        self.assertEqual(len(Package.objects.values()), 2)
163
 
        self.assertEqual(len(Package.objects.values('screening__movie__director__pk')), 2)
164
 
        self.assertEqual(len(Package.objects.values('screening__movie__director__name')), 2)
165
 
        self.assertEqual(len(Package.objects.values('screening__movie__director__pk', 'screening__movie__director__name')), 2)
166
 
        self.assertEqual(len(Package.objects.values('screening__movie__pk', 'screening__movie__director__pk')), 2)
167
 
        self.assertEqual(len(Package.objects.values('screening__movie__pk', 'screening__movie__director__name')), 2)
168
 
        self.assertEqual(len(Package.objects.values('screening__movie__title', 'screening__movie__director__pk')), 2)
169
 
        self.assertEqual(len(Package.objects.values('screening__movie__title', 'screening__movie__director__name')), 2)
170
 
 
171
 
        self.assertEqual(Package.objects.filter(screening__movie__director=self.director).count(), 1)
172
 
        self.assertEqual(Package.objects.exclude(screening__movie__director=self.director).count(), 1)