13
13
from .models import Company , Employee , Number , Experiment
14
14
15
15
16
- class ExpressionsTests (TestCase ):
17
-
18
- def test_filter ( self ):
16
+ class BasicExpressionsTests (TestCase ):
17
+ @ classmethod
18
+ def setUpTestData ( cls ):
19
19
Company .objects .create (
20
20
name = "Example Inc." , num_employees = 2300 , num_chairs = 5 ,
21
21
ceo = Employee .objects .create (firstname = "Joe" , lastname = "Smith" )
@@ -29,16 +29,19 @@ def test_filter(self):
29
29
ceo = Employee .objects .create (firstname = "Max" , lastname = "Mustermann" )
30
30
8000
code>
)
31
31
32
- company_query = Company .objects .values (
32
+ def setUp (self ):
33
+ self .company_query = Company .objects .values (
33
34
"name" , "num_employees" , "num_chairs"
34
35
).order_by (
35
36
"name" , "num_employees" , "num_chairs"
36
37
)
37
38
38
- # We can filter for companies where the number of employees is greater
39
+ def test_filter_inter_attribute (self ):
40
+ # We can filter on attribute relationships on same model obj, e.g.
41
+ # find companies where the number of employees is greater
39
42
# than the number of chairs.
40
43
self .assertQuerysetEqual (
41
- company_query .filter (num_employees__gt = F ("num_chairs" )), [
44
+ self . company_query .filter (num_employees__gt = F ("num_chairs" )), [
42
45
{
43
46
"num_chairs" : 5 ,
44
47
"name" : "Example Inc." ,
@@ -53,11 +56,12 @@ def test_filter(self):
53
56
lambda o : o
54
57
)
55
58
59
+ def test_update (self ):
56
60
# We can set one field to have the value of another field
57
61
# Make sure we have enough chairs
58
- company_query .update (num_chairs = F ("num_employees" ))
62
+ self . company_query .update (num_chairs = F ("num_employees" ))
59
63
self .assertQuerysetEqual (
60
- company_query , [
64
+ self . company_query , [
61
65
{
62
66
"num_chairs" : 2300 ,
63
67
"name" : "Example Inc." ,
@@ -77,11 +81,12 @@ def test_filter(self):
77
81
lambda o : o
78
82
)
79
83
84
+ def test_arithmetic (self ):
80
85
# We can perform arithmetic operations in expressions
81
86
# Make sure we have 2 spare chairs
82
- company_query .update (num_chairs = F ("num_employees" ) + 2 )
87
+ self . company_query .update (num_chairs = F ("num_employees" ) + 2 )
83
88
self .assertQuerysetEqual (
84
- company_query , [
89
+ self . company_query , [
85
90
{
86
91
'num_chairs' : 2302 ,
87
92
'name' : 'Example Inc.' ,
@@ -101,12 +106,13 @@ def test_filter(self):
101
106
lambda o : o ,
102
107
)
103
108
109
+ def test_order_of_operations (self ):
104
110
# Law of order of operations is followed
105
- company_query .update (
111
+ self . company_query .update (
106
112
num_chairs = F ('num_employees' ) + 2 * F ('num_employees' )
107
113
)
108
114
self .assertQuerysetEqual (
109
- company_query , [
115
+ self . company_query , [
110
116
{
111
117
'num_chairs' : 6900 ,
112
118
'name' : 'Example Inc.' ,
@@ -126,12 +132,13 @@ def test_filter(self):
126
132
lambda o : o ,
127
133
)
128
134
135
+ def test_parenthesis_priority (self ):
129
136
# Law of order of operations can be overridden by parentheses
130
- company_query .update (
137
+ self . company_query .update (
131
138
num_chairs = ((F ('num_employees' ) + 2 ) * F ('num_employees' ))
132
139
)
133
140
self .assertQuerysetEqual (
134
- company_query , [
141
+ self . company_query , [
135
142
{
136
143
'num_chairs' : 5294600 ,
137
144
'name' : 'Example Inc.' ,
@@ -151,8 +158,8 @@ def test_filter(self):
151
158
lambda o : o ,
152
159
)
153
160
154
- # The relation of a foreign key can become copied over to an other
155
- # foreign key .
161
+ def test_update_with_fk ( self ):
162
+ # ForeignKey can become updated with the value of another ForeignKey .
156
163
self .assertEqual (
157
164
Company .objects .update (point_of_contact = F ('ceo' )),
158
165
3
@@ -167,11 +174,13 @@ def test_filter(self):
167
174
ordered = False
168
175
)
169
176
177
+ def test_filter_with_join (self ):
178
+ # F Expressions can also span joins
179
+ Company .objects .update (point_of_contact = F ('ceo' ))
170
180
c = Company .objects .all ()[0 ]
171
181
c .point_of_contact = Employee .objects .create (firstname = "Guido" , lastname = "van Rossum" )
172
182
c .save ()
173
183
174
- # F Expressions can also span joins
175
184
self .assertQuerysetEqual (
176
185
Company .objects .filter (ceo__firstname = F ("point_of_contact__firstname" )), [
177
186
"Foobar Ltd." ,
@@ -197,6 +206,7 @@ def test_filter(self):
197
206
ceo__firstname = F ('point_of_contact__firstname' )
198
207
).update (name = F ('point_of_contact__lastname' ))
199
208
209
+ def test_object_update (self ):
200
210
# F expressions can be used to update attributes on single objects
201
211
test_gmbh = Company .objects .get (name = "Test GmbH" )
202
212
self .assertEqual (test_gmbh .num_employees , 32 )
@@ -205,11 +215,10 @@ def test_filter(self):
205
215
test_gmbh = Company .objects .get (pk = test_gmbh .pk )
206
216
self .assertEqual (test_gmbh .num_employees , 36 )
207
217
218
+ def test_object_update_fk (self ):
208
219
# F expressions cannot be used to update attributes which are foreign
209
220
# keys, or attributes which involve joins.
210
- test_gmbh .point_of_contact = None
211
- test_gmbh .save ()
212
- self .assertIsNone (test_gmbh .point_of_contact )
221
+ test_gmbh = Company .objects .get (name = "Test GmbH" )
213
222
214
223
def test ():
215
224
test_gmbh .point_of_contact = F ("ceo" )
@@ -220,8 +229,10 @@ def test():
220
229
test_gmbh .name = F ("ceo__last_name" )
221
230
self .assertRaises (FieldError , test_gmbh .save )
222
231
232
+ def test_object_update_unsaved_objects (self ):
223
233
# F expressions cannot be used to update attributes on objects which do
224
234
# not yet exist in the database
235
+ test_gmbh = Company .objects .get (name = "Test GmbH" )
225
236
acme = Company (
226
237
name = "The Acme Widget Co." , num_employees = 12 , num_chairs = 5 ,
227
238
ceo = test_gmbh .ceo
@@ -287,6 +298,9 @@ def test_ticket_18375_chained_filters(self):
287
298
)
288
299
self .assertEqual (str (qs .query ).count ('JOIN' ), 2 )
289
300
301
+
302
+ class ExpressionsTests (TestCase ):
303
+
290
304
def test_F_object_deepcopy (self ):
291
305
"""
292
306
Make sure F objects can be deepcopied (#23492)
0 commit comments