~ubuntu-branches/debian/sid/python-django/sid

« back to all changes in this revision

Viewing changes to tests/select_related_regress/tests.py

  • Committer: Package Import Robot
  • Author(s): Luke Faraone
  • Date: 2013-11-07 15:33:49 UTC
  • mfrom: (1.3.12)
  • Revision ID: package-import@ubuntu.com-20131107153349-e31sc149l2szs3jb
Tags: 1.6-1
* New upstream version. Closes: #557474, #724637.
* python-django now also suggests the installation of ipython,
  bpython, python-django-doc, and libgdal1.
  Closes: #636511, #686333, #704203
* Set package maintainer to Debian Python Modules Team.
* Bump standards version to 3.9.5, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from __future__ import absolute_import, unicode_literals
 
2
 
 
3
from django.test import TestCase
 
4
from django.utils import six
 
5
 
 
6
from .models import (Building, Child, Device, Port, Item, Country, Connection,
 
7
    ClientStatus, State, Client, SpecialClient, TUser, Person, Student,
 
8
    Organizer, Class, Enrollment, Hen, Chick)
 
9
 
 
10
 
 
11
class SelectRelatedRegressTests(TestCase):
 
12
 
 
13
    def test_regression_7110(self):
 
14
        """
 
15
        Regression test for bug #7110.
 
16
 
 
17
        When using select_related(), we must query the
 
18
        Device and Building tables using two different aliases (each) in order to
 
19
        differentiate the start and end Connection fields. The net result is that
 
20
        both the "connections = ..." queries here should give the same results
 
21
        without pulling in more than the absolute minimum number of tables
 
22
        (history has shown that it's easy to make a mistake in the implementation
 
23
        and include some unnecessary bonus joins).
 
24
        """
 
25
 
 
26
        b=Building.objects.create(name='101')
 
27
        dev1=Device.objects.create(name="router", building=b)
 
28
        dev2=Device.objects.create(name="switch", building=b)
 
29
        dev3=Device.objects.create(name="server", building=b)
 
30
        port1=Port.objects.create(port_number='4',device=dev1)
 
31
        port2=Port.objects.create(port_number='7',device=dev2)
 
32
        port3=Port.objects.create(port_number='1',device=dev3)
 
33
        c1=Connection.objects.create(start=port1, end=port2)
 
34
        c2=Connection.objects.create(start=port2, end=port3)
 
35
 
 
36
        connections=Connection.objects.filter(start__device__building=b, end__device__building=b).order_by('id')
 
37
        self.assertEqual([(c.id, six.text_type(c.start), six.text_type(c.end)) for c in connections],
 
38
            [(c1.id, 'router/4', 'switch/7'), (c2.id, 'switch/7', 'server/1')])
 
39
 
 
40
        connections=Connection.objects.filter(start__device__building=b, end__device__building=b).select_related().order_by('id')
 
41
        self.assertEqual([(c.id, six.text_type(c.start), six.text_type(c.end)) for c in connections],
 
42
            [(c1.id, 'router/4', 'switch/7'), (c2.id, 'switch/7', 'server/1')])
 
43
 
 
44
        # This final query should only have seven tables (port, device and building
 
45
        # twice each, plus connection once). Thus, 6 joins plus the FROM table.
 
46
        self.assertEqual(str(connections.query).count(" JOIN "), 6)
 
47
 
 
48
 
 
49
    def test_regression_8106(self):
 
50
        """
 
51
        Regression test for bug #8106.
 
52
 
 
53
        Same sort of problem as the previous test, but this time there are
 
54
        more extra tables to pull in as part of the select_related() and some
 
55
        of them could potentially clash (so need to be kept separate).
 
56
        """
 
57
 
 
58
        us = TUser.objects.create(name="std")
 
59
        usp = Person.objects.create(user=us)
 
60
        uo = TUser.objects.create(name="org")
 
61
        uop = Person.objects.create(user=uo)
 
62
        s = Student.objects.create(person = usp)
 
63
        o = Organizer.objects.create(person = uop)
 
64
        c = Class.objects.create(org=o)
 
65
        e = Enrollment.objects.create(std=s, cls=c)
 
66
 
 
67
        e_related = Enrollment.objects.all().select_related()[0]
 
68
        self.assertEqual(e_related.std.person.user.name, "std")
 
69
        self.assertEqual(e_related.cls.org.person.user.name, "org")
 
70
 
 
71
    def test_regression_8036(self):
 
72
        """
 
73
        Regression test for bug #8036
 
74
 
 
75
        the first related model in the tests below
 
76
        ("state") is empty and we try to select the more remotely related
 
77
        state__country. The regression here was not skipping the empty column results
 
78
        for country before getting status.
 
79
        """
 
80
 
 
81
        australia = Country.objects.create(name='Australia')
 
82
        active = ClientStatus.objects.create(name='active')
 
83
        client = Client.objects.create(name='client', status=active)
 
84
 
 
85
        self.assertEqual(client.status, active)
 
86
        self.assertEqual(Client.objects.select_related()[0].status, active)
 
87
        self.assertEqual(Client.objects.select_related('state')[0].status, active)
 
88
        self.assertEqual(Client.objects.select_related('state', 'status')[0].status, active)
 
89
        self.assertEqual(Client.objects.select_related('state__country')[0].status, active)
 
90
        self.assertEqual(Client.objects.select_related('state__country', 'status')[0].status, active)
 
91
        self.assertEqual(Client.objects.select_related('status')[0].status, active)
 
92
 
 
93
    def test_multi_table_inheritance(self):
 
94
        """ Exercising select_related() with multi-table model inheritance. """
 
95
        c1 = Child.objects.create(name="child1", value=42)
 
96
        i1 = Item.objects.create(name="item1", child=c1)
 
97
        i2 = Item.objects.create(name="item2")
 
98
 
 
99
        self.assertQuerysetEqual(
 
100
                Item.objects.select_related("child").order_by("name"),
 
101
                ["<Item: item1>", "<Item: item2>"]
 
102
        )
 
103
 
 
104
    def test_regression_12851(self):
 
105
        """
 
106
        Regression for #12851
 
107
 
 
108
        Deferred fields are used correctly if you select_related a subset
 
109
        of fields.
 
110
        """
 
111
        australia = Country.objects.create(name='Australia')
 
112
        active = ClientStatus.objects.create(name='active')
 
113
 
 
114
        wa = State.objects.create(name="Western Australia", country=australia)
 
115
        c1 = Client.objects.create(name='Brian Burke', state=wa, status=active)
 
116
        burke = Client.objects.select_related('state').defer('state__name').get(name='Brian Burke')
 
117
 
 
118
        self.assertEqual(burke.name, 'Brian Burke')
 
119
        self.assertEqual(burke.state.name, 'Western Australia')
 
120
 
 
121
        # Still works if we're dealing with an inherited class
 
122
        sc1 = SpecialClient.objects.create(name='Troy Buswell', state=wa, status=active, value=42)
 
123
        troy = SpecialClient.objects.select_related('state').defer('state__name').get(name='Troy Buswell')
 
124
 
 
125
        self.assertEqual(troy.name, 'Troy Buswell')
 
126
        self.assertEqual(troy.value, 42)
 
127
        self.assertEqual(troy.state.name, 'Western Australia')
 
128
 
 
129
        # Still works if we defer an attribute on the inherited class
 
130
        troy = SpecialClient.objects.select_related('state').defer('value', 'state__name').get(name='Troy Buswell')
 
131
 
 
132
        self.assertEqual(troy.name, 'Troy Buswell')
 
133
        self.assertEqual(troy.value, 42)
 
134
        self.assertEqual(troy.state.name, 'Western Australia')
 
135
 
 
136
        # Also works if you use only, rather than defer
 
137
        troy = SpecialClient.objects.select_related('state').only('name', 'state').get(name='Troy Buswell')
 
138
 
 
139
        self.assertEqual(troy.name, 'Troy Buswell')
 
140
        self.assertEqual(troy.value, 42)
 
141
        self.assertEqual(troy.state.name, 'Western Australia')
 
142
 
 
143
    def test_null_join_promotion(self):
 
144
        australia = Country.objects.create(name='Australia')
 
145
        active = ClientStatus.objects.create(name='active')
 
146
 
 
147
        wa = State.objects.create(name="Western Australia", country=australia)
 
148
        bob = Client.objects.create(name='Bob', status=active)
 
149
        jack = Client.objects.create(name='Jack', status=active, state=wa)
 
150
        qs = Client.objects.filter(state=wa).select_related('state')
 
151
        with self.assertNumQueries(1):
 
152
            self.assertEqual(list(qs), [jack])
 
153
            self.assertEqual(qs[0].state, wa)
 
154
            # The select_related join wasn't promoted as there was already an
 
155
            # existing (even if trimmed) inner join to state.
 
156
            self.assertFalse('LEFT OUTER' in str(qs.query))
 
157
        qs = Client.objects.select_related('state').order_by('name')
 
158
        with self.assertNumQueries(1):
 
159
            self.assertEqual(list(qs), [bob, jack])
 
160
            self.assertIs(qs[0].state, None)
 
161
            self.assertEqual(qs[1].state, wa)
 
162
            # The select_related join was promoted as there is already an
 
163
            # existing join.
 
164
            self.assertTrue('LEFT OUTER' in str(qs.query))
 
165
 
 
166
    def test_regression_19870(self):
 
167
        """
 
168
        Regression for #19870
 
169
 
 
170
        """
 
171
        hen = Hen.objects.create(name='Hen')
 
172
        chick = Chick.objects.create(name='Chick', mother=hen)
 
173
 
 
174
        self.assertEqual(Chick.objects.all()[0].mother.name, 'Hen')
 
175
        self.assertEqual(Chick.objects.select_related()[0].mother.name, 'Hen')