tests.py 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083
  1. from __future__ import unicode_literals
  2. from datetime import date, datetime, time, timedelta
  3. from decimal import Decimal
  4. from operator import attrgetter, itemgetter
  5. from uuid import UUID
  6. from django.core.exceptions import FieldError
  7. from django.db import models
  8. from django.db.models import F, Q, Value, Min, Max
  9. from django.db.models.expressions import Case, When
  10. from django.test import TestCase
  11. from django.utils import six
  12. from .models import CaseTestModel, O2OCaseTestModel, FKCaseTestModel, Client
  13. class CaseExpressionTests(TestCase):
  14. @classmethod
  15. def setUpTestData(cls):
  16. o = CaseTestModel.objects.create(integer=1, integer2=1, string='1')
  17. O2OCaseTestModel.objects.create(o2o=o, integer=1)
  18. FKCaseTestModel.objects.create(fk=o, integer=1)
  19. o = CaseTestModel.objects.create(integer=2, integer2=3, string='2')
  20. O2OCaseTestModel.objects.create(o2o=o, integer=2)
  21. FKCaseTestModel.objects.create(fk=o, integer=2)
  22. FKCaseTestModel.objects.create(fk=o, integer=3)
  23. o = CaseTestModel.objects.create(integer=3, integer2=4, string='3')
  24. O2OCaseTestModel.objects.create(o2o=o, integer=3)
  25. FKCaseTestModel.objects.create(fk=o, integer=3)
  26. FKCaseTestModel.objects.create(fk=o, integer=4)
  27. o = CaseTestModel.objects.create(integer=2, integer2=2, string='2')
  28. O2OCaseTestModel.objects.create(o2o=o, integer=2)
  29. FKCaseTestModel.objects.create(fk=o, integer=2)
  30. FKCaseTestModel.objects.create(fk=o, integer=3)
  31. o = CaseTestModel.objects.create(integer=3, integer2=4, string='3')
  32. O2OCaseTestModel.objects.create(o2o=o, integer=3)
  33. FKCaseTestModel.objects.create(fk=o, integer=3)
  34. FKCaseTestModel.objects.create(fk=o, integer=4)
  35. o = CaseTestModel.objects.create(integer=3, integer2=3, string='3')
  36. O2OCaseTestModel.objects.create(o2o=o, integer=3)
  37. FKCaseTestModel.objects.create(fk=o, integer=3)
  38. FKCaseTestModel.objects.create(fk=o, integer=4)
  39. o = CaseTestModel.objects.create(integer=4, integer2=5, string='4')
  40. O2OCaseTestModel.objects.create(o2o=o, integer=1)
  41. FKCaseTestModel.objects.create(fk=o, integer=5)
  42. # GROUP BY on Oracle fails with TextField/BinaryField; see #24096.
  43. cls.non_lob_fields = [
  44. f.name for f in CaseTestModel._meta.get_fields()
  45. if not (f.is_relation and f.auto_created) and not isinstance(f, (models.BinaryField, models.TextField))
  46. ]
  47. def test_annotate(self):
  48. self.assertQuerysetEqual(
  49. CaseTestModel.objects.annotate(test=Case(
  50. When(integer=1, then=Value('one')),
  51. When(integer=2, then=Value('two')),
  52. default=Value('other'),
  53. output_field=models.CharField(),
  54. )).order_by('pk'),
  55. [(1, 'one'), (2, 'two'), (3, 'other'), (2, 'two'), (3, 'other'), (3, 'other'), (4, 'other')],
  56. transform=attrgetter('integer', 'test')
  57. )
  58. def test_annotate_without_default(self):
  59. self.assertQuerysetEqual(
  60. CaseTestModel.objects.annotate(test=Case(
  61. When(integer=1, then=Value(1)),
  62. When(integer=2, then=Value(2)),
  63. output_field=models.IntegerField(),
  64. )).order_by('pk'),
  65. [(1, 1), (2, 2), (3, None), (2, 2), (3, None), (3, None), (4, None)],
  66. transform=attrgetter('integer', 'test')
  67. )
  68. def test_annotate_with_expression_as_value(self):
  69. self.assertQuerysetEqual(
  70. CaseTestModel.objects.annotate(f_test=Case(
  71. When(integer=1, then=F('integer') + 1),
  72. When(integer=2, then=F('integer') + 3),
  73. default='integer',
  74. )).order_by('pk'),
  75. [(1, 2), (2, 5), (3, 3), (2, 5), (3, 3), (3, 3), (4, 4)],
  76. transform=attrgetter('integer', 'f_test')
  77. )
  78. def test_annotate_with_expression_as_condition(self):
  79. self.assertQuerysetEqual(
  80. CaseTestModel.objects.annotate(f_test=Case(
  81. When(integer2=F('integer'), then=Value('equal')),
  82. When(integer2=F('integer') + 1, then=Value('+1')),
  83. output_field=models.CharField(),
  84. )).order_by('pk'),
  85. [(1, 'equal'), (2, '+1'), (3, '+1'), (2, 'equal'), (3, '+1'), (3, 'equal'), (4, '+1')],
  86. transform=attrgetter('integer', 'f_test')
  87. )
  88. def test_annotate_with_join_in_value(self):
  89. self.assertQuerysetEqual(
  90. CaseTestModel.objects.annotate(join_test=Case(
  91. When(integer=1, then=F('o2o_rel__integer') + 1),
  92. When(integer=2, then=F('o2o_rel__integer') + 3),
  93. default='o2o_rel__integer',
  94. )).order_by('pk'),
  95. [(1, 2), (2, 5), (3, 3), (2, 5), (3, 3), (3, 3), (4, 1)],
  96. transform=attrgetter('integer', 'join_test')
  97. )
  98. def test_annotate_with_join_in_condition(self):
  99. self.assertQuerysetEqual(
  100. CaseTestModel.objects.annotate(join_test=Case(
  101. When(integer2=F('o2o_rel__integer'), then=Value('equal')),
  102. When(integer2=F('o2o_rel__integer') + 1, then=Value('+1')),
  103. default=Value('other'),
  104. output_field=models.CharField(),
  105. )).order_by('pk'),
  106. [(1, 'equal'), (2, '+1'), (3, '+1'), (2, 'equal'), (3, '+1'), (3, 'equal'), (4, 'other')],
  107. transform=attrgetter('integer', 'join_test')
  108. )
  109. def test_annotate_with_join_in_predicate(self):
  110. self.assertQuerysetEqual(
  111. CaseTestModel.objects.annotate(join_test=Case(
  112. When(o2o_rel__integer=1, then=Value('one')),
  113. When(o2o_rel__integer=2, then=Value('two')),
  114. When(o2o_rel__integer=3, then=Value('three')),
  115. default=Value('other'),
  116. output_field=models.CharField(),
  117. )).order_by('pk'),
  118. [(1, 'one'), (2, 'two'), (3, 'three'), (2, 'two'), (3, 'three'), (3, 'three'), (4, 'one')],
  119. transform=attrgetter('integer', 'join_test')
  120. )
  121. def test_annotate_with_annotation_in_value(self):
  122. self.assertQuerysetEqual(
  123. CaseTestModel.objects.annotate(
  124. f_plus_1=F('integer') + 1,
  125. f_plus_3=F('integer') + 3,
  126. ).annotate(
  127. f_test=Case(
  128. When(integer=1, then='f_plus_1'),
  129. When(integer=2, then='f_plus_3'),
  130. default='integer',
  131. ),
  132. ).order_by('pk'),
  133. [(1, 2), (2, 5), (3, 3), (2, 5), (3, 3), (3, 3), (4, 4)],
  134. transform=attrgetter('integer', 'f_test')
  135. )
  136. def test_annotate_with_annotation_in_condition(self):
  137. self.assertQuerysetEqual(
  138. CaseTestModel.objects.annotate(
  139. f_plus_1=F('integer') + 1,
  140. ).annotate(
  141. f_test=Case(
  142. When(integer2=F('integer'), then=Value('equal')),
  143. When(integer2=F('f_plus_1'), then=Value('+1')),
  144. output_field=models.CharField(),
  145. ),
  146. ).order_by('pk'),
  147. [(1, 'equal'), (2, '+1'), (3, '+1'), (2, 'equal'), (3, '+1'), (3, 'equal'), (4, '+1')],
  148. transform=attrgetter('integer', 'f_test')
  149. )
  150. def test_annotate_with_annotation_in_predicate(self):
  151. self.assertQuerysetEqual(
  152. CaseTestModel.objects.annotate(
  153. f_minus_2=F('integer') - 2,
  154. ).annotate(
  155. test=Case(
  156. When(f_minus_2=-1, then=Value('negative one')),
  157. When(f_minus_2=0, then=Value('zero')),
  158. When(f_minus_2=1, then=Value('one')),
  159. default=Value('other'),
  160. output_field=models.CharField(),
  161. ),
  162. ).order_by('pk'),
  163. [(1, 'negative one'), (2, 'zero'), (3, 'one'), (2, 'zero'), (3, 'one'), (3, 'one'), (4, 'other')],
  164. transform=attrgetter('integer', 'test')
  165. )
  166. def test_annotate_with_aggregation_in_value(self):
  167. self.assertQuerysetEqual(
  168. CaseTestModel.objects.values(*self.non_lob_fields).annotate(
  169. min=Min('fk_rel__integer'),
  170. max=Max('fk_rel__integer'),
  171. ).annotate(
  172. test=Case(
  173. When(integer=2, then='min'),
  174. When(integer=3, then='max'),
  175. ),
  176. ).order_by('pk'),
  177. [(1, None, 1, 1), (2, 2, 2, 3), (3, 4, 3, 4), (2, 2, 2, 3), (3, 4, 3, 4), (3, 4, 3, 4), (4, None, 5, 5)],
  178. transform=itemgetter('integer', 'test', 'min', 'max')
  179. )
  180. def test_annotate_with_aggregation_in_condition(self):
  181. self.assertQuerysetEqual(
  182. CaseTestModel.objects.values(*self.non_lob_fields).annotate(
  183. min=Min('fk_rel__integer'),
  184. max=Max('fk_rel__integer'),
  185. ).annotate(
  186. test=Case(
  187. When(integer2=F('min'), then=Value('min')),
  188. When(integer2=F('max'), then=Value('max')),
  189. output_field=models.CharField(),
  190. ),
  191. ).order_by('pk'),
  192. [(1, 1, 'min'), (2, 3, 'max'), (3, 4, 'max'), (2, 2, 'min'), (3, 4, 'max'), (3, 3, 'min'), (4, 5, 'min')],
  193. transform=itemgetter('integer', 'integer2', 'test')
  194. )
  195. def test_annotate_with_aggregation_in_predicate(self):
  196. self.assertQuerysetEqual(
  197. CaseTestModel.objects.values(*self.non_lob_fields).annotate(
  198. max=Max('fk_rel__integer'),
  199. ).annotate(
  200. test=Case(
  201. When(max=3, then=Value('max = 3')),
  202. When(max=4, then=Value('max = 4')),
  203. default=Value(''),
  204. output_field=models.CharField(),
  205. ),
  206. ).order_by('pk'),
  207. [(1, 1, ''), (2, 3, 'max = 3'), (3, 4, 'max = 4'), (2, 3, 'max = 3'),
  208. (3, 4, 'max = 4'), (3, 4, 'max = 4'), (4, 5, '')],
  209. transform=itemgetter('integer', 'max', 'test')
  210. )
  211. def test_combined_expression(self):
  212. self.assertQuerysetEqual(
  213. CaseTestModel.objects.annotate(
  214. test=Case(
  215. When(integer=1, then=Value(2)),
  216. When(integer=2, then=Value(1)),
  217. default=Value(3),
  218. output_field=models.IntegerField(),
  219. ) + 1,
  220. ).order_by('pk'),
  221. [(1, 3), (2, 2), (3, 4), (2, 2), (3, 4), (3, 4), (4, 4)],
  222. transform=attrgetter('integer', 'test')
  223. )
  224. def test_in_subquery(self):
  225. self.assertQuerysetEqual(
  226. CaseTestModel.objects.filter(
  227. pk__in=CaseTestModel.objects.annotate(
  228. test=Case(
  229. When(integer=F('integer2'), then='pk'),
  230. When(integer=4, then='pk'),
  231. output_field=models.IntegerField(),
  232. ),
  233. ).values('test')).order_by('pk'),
  234. [(1, 1), (2, 2), (3, 3), (4, 5)],
  235. transform=attrgetter('integer', 'integer2')
  236. )
  237. def test_aggregate(self):
  238. self.assertEqual(
  239. CaseTestModel.objects.aggregate(
  240. one=models.Sum(Case(
  241. When(integer=1, then=Value(1)),
  242. output_field=models.IntegerField(),
  243. )),
  244. two=models.Sum(Case(
  245. When(integer=2, then=Value(1)),
  246. output_field=models.IntegerField(),
  247. )),
  248. three=models.Sum(Case(
  249. When(integer=3, then=Value(1)),
  250. output_field=models.IntegerField(),
  251. )),
  252. four=models.Sum(Case(
  253. When(integer=4, then=Value(1)),
  254. output_field=models.IntegerField(),
  255. )),
  256. ),
  257. {'one': 1, 'two': 2, 'three': 3, 'four': 1}
  258. )
  259. def test_aggregate_with_expression_as_value(self):
  260. self.assertEqual(
  261. CaseTestModel.objects.aggregate(
  262. one=models.Sum(Case(When(integer=1, then='integer'))),
  263. two=models.Sum(Case(When(integer=2, then=F('integer') - 1))),
  264. three=models.Sum(Case(When(integer=3, then=F('integer') + 1))),
  265. ),
  266. {'one': 1, 'two': 2, 'three': 12}
  267. )
  268. def test_aggregate_with_expression_as_condition(self):
  269. self.assertEqual(
  270. CaseTestModel.objects.aggregate(
  271. equal=models.Sum(Case(
  272. When(integer2=F('integer'), then=Value(1)),
  273. output_field=models.IntegerField(),
  274. )),
  275. plus_one=models.Sum(Case(
  276. When(integer2=F('integer') + 1, then=Value(1)),
  277. output_field=models.IntegerField(),
  278. )),
  279. ),
  280. {'equal': 3, 'plus_one': 4}
  281. )
  282. def test_filter(self):
  283. self.assertQuerysetEqual(
  284. CaseTestModel.objects.filter(integer2=Case(
  285. When(integer=2, then=Value(3)),
  286. When(integer=3, then=Value(4)),
  287. default=Value(1),
  288. output_field=models.IntegerField(),
  289. )).order_by('pk'),
  290. [(1, 1), (2, 3), (3, 4), (3, 4)],
  291. transform=attrgetter('integer', 'integer2')
  292. )
  293. def test_filter_without_default(self):
  294. self.assertQuerysetEqual(
  295. CaseTestModel.objects.filter(integer2=Case(
  296. When(integer=2, then=Value(3)),
  297. When(integer=3, then=Value(4)),
  298. output_field=models.IntegerField(),
  299. )).order_by('pk'),
  300. [(2, 3), (3, 4), (3, 4)],
  301. transform=attrgetter('integer', 'integer2')
  302. )
  303. def test_filter_with_expression_as_value(self):
  304. self.assertQuerysetEqual(
  305. CaseTestModel.objects.filter(integer2=Case(
  306. When(integer=2, then=F('integer') + 1),
  307. When(integer=3, then=F('integer')),
  308. default='integer',
  309. )).order_by('pk'),
  310. [(1, 1), (2, 3), (3, 3)],
  311. transform=attrgetter('integer', 'integer2')
  312. )
  313. def test_filter_with_expression_as_condition(self):
  314. self.assertQuerysetEqual(
  315. CaseTestModel.objects.filter(string=Case(
  316. When(integer2=F('integer'), then=Value('2')),
  317. When(integer2=F('integer') + 1, then=Value('3')),
  318. output_field=models.CharField(),
  319. )).order_by('pk'),
  320. [(3, 4, '3'), (2, 2, '2'), (3, 4, '3')],
  321. transform=attrgetter('integer', 'integer2', 'string')
  322. )
  323. def test_filter_with_join_in_value(self):
  324. self.assertQuerysetEqual(
  325. CaseTestModel.objects.filter(integer2=Case(
  326. When(integer=2, then=F('o2o_rel__integer') + 1),
  327. When(integer=3, then=F('o2o_rel__integer')),
  328. default='o2o_rel__integer',
  329. )).order_by('pk'),
  330. [(1, 1), (2, 3), (3, 3)],
  331. transform=attrgetter('integer', 'integer2')
  332. )
  333. def test_filter_with_join_in_condition(self):
  334. self.assertQuerysetEqual(
  335. CaseTestModel.objects.filter(integer=Case(
  336. When(integer2=F('o2o_rel__integer') + 1, then=Value(2)),
  337. When(integer2=F('o2o_rel__integer'), then=Value(3)),
  338. output_field=models.IntegerField(),
  339. )).order_by('pk'),
  340. [(2, 3), (3, 3)],
  341. transform=attrgetter('integer', 'integer2')
  342. )
  343. def test_filter_with_join_in_predicate(self):
  344. self.assertQuerysetEqual(
  345. CaseTestModel.objects.filter(integer2=Case(
  346. When(o2o_rel__integer=1, then=Value(1)),
  347. When(o2o_rel__integer=2, then=Value(3)),
  348. When(o2o_rel__integer=3, then=Value(4)),
  349. output_field=models.IntegerField(),
  350. )).order_by('pk'),
  351. [(1, 1), (2, 3), (3, 4), (3, 4)],
  352. transform=attrgetter('integer', 'integer2')
  353. )
  354. def test_filter_with_annotation_in_value(self):
  355. self.assertQuerysetEqual(
  356. CaseTestModel.objects.annotate(
  357. f=F('integer'),
  358. f_plus_1=F('integer') + 1,
  359. ).filter(
  360. integer2=Case(
  361. When(integer=2, then='f_plus_1'),
  362. When(integer=3, then='f'),
  363. ),
  364. ).order_by('pk'),
  365. [(2, 3), (3, 3)],
  366. transform=attrgetter('integer', 'integer2')
  367. )
  368. def test_filter_with_annotation_in_condition(self):
  369. self.assertQuerysetEqual(
  370. CaseTestModel.objects.annotate(
  371. f_plus_1=F('integer') + 1,
  372. ).filter(
  373. integer=Case(
  374. When(integer2=F('integer'), then=Value(2)),
  375. When(integer2=F('f_plus_1'), then=Value(3)),
  376. output_field=models.IntegerField(),
  377. ),
  378. ).order_by('pk'),
  379. [(3, 4), (2, 2), (3, 4)],
  380. transform=attrgetter('integer', 'integer2')
  381. )
  382. def test_filter_with_annotation_in_predicate(self):
  383. self.assertQuerysetEqual(
  384. CaseTestModel.objects.annotate(
  385. f_plus_1=F('integer') + 1,
  386. ).filter(
  387. integer2=Case(
  388. When(f_plus_1=3, then=Value(3)),
  389. When(f_plus_1=4, then=Value(4)),
  390. default=Value(1),
  391. output_field=models.IntegerField(),
  392. ),
  393. ).order_by('pk'),
  394. [(1, 1), (2, 3), (3, 4), (3, 4)],
  395. transform=attrgetter('integer', 'integer2')
  396. )
  397. def test_filter_with_aggregation_in_value(self):
  398. self.assertQuerysetEqual(
  399. CaseTestModel.objects.values(*self.non_lob_fields).annotate(
  400. min=Min('fk_rel__integer'),
  401. max=Max('fk_rel__integer'),
  402. ).filter(
  403. integer2=Case(
  404. When(integer=2, then='min'),
  405. When(integer=3, then='max'),
  406. ),
  407. ).order_by('pk'),
  408. [(3, 4, 3, 4), (2, 2, 2, 3), (3, 4, 3, 4)],
  409. transform=itemgetter('integer', 'integer2', 'min', 'max')
  410. )
  411. def test_filter_with_aggregation_in_condition(self):
  412. self.assertQuerysetEqual(
  413. CaseTestModel.objects.values(*self.non_lob_fields).annotate(
  414. min=Min('fk_rel__integer'),
  415. max=Max('fk_rel__integer'),
  416. ).filter(
  417. integer=Case(
  418. When(integer2=F('min'), then=Value(2)),
  419. When(integer2=F('max'), then=Value(3)),
  420. ),
  421. ).order_by('pk'),
  422. [(3, 4, 3, 4), (2, 2, 2, 3), (3, 4, 3, 4)],
  423. transform=itemgetter('integer', 'integer2', 'min', 'max')
  424. )
  425. def test_filter_with_aggregation_in_predicate(self):
  426. self.assertQuerysetEqual(
  427. CaseTestModel.objects.values(*self.non_lob_fields).annotate(
  428. max=Max('fk_rel__integer'),
  429. ).filter(
  430. integer=Case(
  431. When(max=3, then=Value(2)),
  432. When(max=4, then=Value(3)),
  433. ),
  434. ).order_by('pk'),
  435. [(2, 3, 3), (3, 4, 4), (2, 2, 3), (3, 4, 4), (3, 3, 4)],
  436. transform=itemgetter('integer', 'integer2', 'max')
  437. )
  438. def test_update(self):
  439. CaseTestModel.objects.update(
  440. string=Case(
  441. When(integer=1, then=Value('one')),
  442. When(integer=2, then=Value('two')),
  443. default=Value('other'),
  444. ),
  445. )
  446. self.assertQuerysetEqual(
  447. CaseTestModel.objects.all().order_by('pk'),
  448. [(1, 'one'), (2, 'two'), (3, 'other'), (2, 'two'), (3, 'other'), (3, 'other'), (4, 'other')],
  449. transform=attrgetter('integer', 'string')
  450. )
  451. def test_update_without_default(self):
  452. CaseTestModel.objects.update(
  453. integer2=Case(
  454. When(integer=1, then=Value(1)),
  455. When(integer=2, then=Value(2)),
  456. ),
  457. )
  458. self.assertQuerysetEqual(
  459. CaseTestModel.objects.all().order_by('pk'),
  460. [(1, 1), (2, 2), (3, None), (2, 2), (3, None), (3, None), (4, None)],
  461. transform=attrgetter('integer', 'integer2')
  462. )
  463. def test_update_with_expression_as_value(self):
  464. CaseTestModel.objects.update(
  465. integer=Case(
  466. When(integer=1, then=F('integer') + 1),
  467. When(integer=2, then=F('integer') + 3),
  468. default='integer',
  469. ),
  470. )
  471. self.assertQuerysetEqual(
  472. CaseTestModel.objects.all().order_by('pk'),
  473. [('1', 2), ('2', 5), ('3', 3), ('2', 5), ('3', 3), ('3', 3), ('4', 4)],
  474. transform=attrgetter('string', 'integer')
  475. )
  476. def test_update_with_expression_as_condition(self):
  477. CaseTestModel.objects.update(
  478. string=Case(
  479. When(integer2=F('integer'), then=Value('equal')),
  480. When(integer2=F('integer') + 1, then=Value('+1')),
  481. ),
  482. )
  483. self.assertQuerysetEqual(
  484. CaseTestModel.objects.all().order_by('pk'),
  485. [(1, 'equal'), (2, '+1'), (3, '+1'), (2, 'equal'), (3, '+1'), (3, 'equal'), (4, '+1')],
  486. transform=attrgetter('integer', 'string')
  487. )
  488. def test_update_with_join_in_condition_raise_field_error(self):
  489. with self.assertRaisesMessage(FieldError, 'Joined field references are not permitted in this query'):
  490. CaseTestModel.objects.update(
  491. integer=Case(
  492. When(integer2=F('o2o_rel__integer') + 1, then=Value(2)),
  493. When(integer2=F('o2o_rel__integer'), then=Value(3)),
  494. output_field=models.IntegerField(),
  495. ),
  496. )
  497. def test_update_with_join_in_predicate_raise_field_error(self):
  498. with self.assertRaisesMessage(FieldError, 'Joined field references are not permitted in this query'):
  499. CaseTestModel.objects.update(
  500. string=Case(
  501. When(o2o_rel__integer=1, then=Value('one')),
  502. When(o2o_rel__integer=2, then=Value('two')),
  503. When(o2o_rel__integer=3, then=Value('three')),
  504. default=Value('other'),
  505. output_field=models.CharField(),
  506. ),
  507. )
  508. def test_update_big_integer(self):
  509. CaseTestModel.objects.update(
  510. big_integer=Case(
  511. When(integer=1, then=Value(1)),
  512. When(integer=2, then=Value(2)),
  513. ),
  514. )
  515. self.assertQuerysetEqual(
  516. CaseTestModel.objects.all().order_by('pk'),
  517. [(1, 1), (2, 2), (3, None), (2, 2), (3, None), (3, None), (4, None)],
  518. transform=attrgetter('integer', 'big_integer')
  519. )
  520. def test_update_binary(self):
  521. CaseTestModel.objects.update(
  522. binary=Case(
  523. # fails on postgresql on Python 2.7 if output_field is not
  524. # set explicitly
  525. When(integer=1, then=Value(b'one', output_field=models.BinaryField())),
  526. When(integer=2, then=Value(b'two', output_field=models.BinaryField())),
  527. default=Value(b'', output_field=models.BinaryField()),
  528. ),
  529. )
  530. self.assertQuerysetEqual(
  531. CaseTestModel.objects.all().order_by('pk'),
  532. [(1, b'one'), (2, b'two'), (3, b''), (2, b'two'), (3, b''), (3, b''), (4, b'')],
  533. transform=lambda o: (o.integer, six.binary_type(o.binary))
  534. )
  535. def test_update_boolean(self):
  536. CaseTestModel.objects.update(
  537. boolean=Case(
  538. When(integer=1, then=Value(True)),
  539. When(integer=2, then=Value(True)),
  540. default=Value(False),
  541. ),
  542. )
  543. self.assertQuerysetEqual(
  544. CaseTestModel.objects.all().order_by('pk'),
  545. [(1, True), (2, True), (3, False), (2, True), (3, False), (3, False), (4, False)],
  546. transform=attrgetter('integer', 'boolean')
  547. )
  548. def test_update_comma_separated_integer(self):
  549. CaseTestModel.objects.update(
  550. comma_separated_integer=Case(
  551. When(integer=1, then=Value('1')),
  552. When(integer=2, then=Value('2,2')),
  553. default=Value(''),
  554. ),
  555. )
  556. self.assertQuerysetEqual(
  557. CaseTestModel.objects.all().order_by('pk'),
  558. [(1, '1'), (2, '2,2'), (3, ''), (2, '2,2'), (3, ''), (3, ''), (4, '')],
  559. transform=attrgetter('integer', 'comma_separated_integer')
  560. )
  561. def test_update_date(self):
  562. CaseTestModel.objects.update(
  563. date=Case(
  564. When(integer=1, then=Value(date(2015, 1, 1))),
  565. When(integer=2, then=Value(date(2015, 1, 2))),
  566. ),
  567. )
  568. self.assertQuerysetEqual(
  569. CaseTestModel.objects.all().order_by('pk'),
  570. [
  571. (1, date(2015, 1, 1)), (2, date(2015, 1, 2)), (3, None), (2, date(2015, 1, 2)),
  572. (3, None), (3, None), (4, None)
  573. ],
  574. transform=attrgetter('integer', 'date')
  575. )
  576. def test_update_date_time(self):
  577. CaseTestModel.objects.update(
  578. date_time=Case(
  579. When(integer=1, then=Value(datetime(2015, 1, 1))),
  580. When(integer=2, then=Value(datetime(2015, 1, 2))),
  581. ),
  582. )
  583. self.assertQuerysetEqual(
  584. CaseTestModel.objects.all().order_by('pk'),
  585. [
  586. (1, datetime(2015, 1, 1)), (2, datetime(2015, 1, 2)), (3, None), (2, datetime(2015, 1, 2)),
  587. (3, None), (3, None), (4, None)
  588. ],
  589. transform=attrgetter('integer', 'date_time')
  590. )
  591. def test_update_decimal(self):
  592. CaseTestModel.objects.update(
  593. decimal=Case(
  594. When(integer=1, then=Value(Decimal('1.1'))),
  595. When(integer=2, then=Value(Decimal('2.2'))),
  596. ),
  597. )
  598. self.assertQuerysetEqual(
  599. CaseTestModel.objects.all().order_by('pk'),
  600. [(1, Decimal('1.1')), (2, Decimal('2.2')), (3, None), (2, Decimal('2.2')), (3, None), (3, None), (4, None)],
  601. transform=attrgetter('integer', 'decimal')
  602. )
  603. def test_update_duration(self):
  604. CaseTestModel.objects.update(
  605. duration=Case(
  606. # fails on sqlite if output_field is not set explicitly on all
  607. # Values containing timedeltas
  608. When(integer=1, then=Value(timedelta(1), output_field=models.DurationField())),
  609. When(integer=2, then=Value(timedelta(2), output_field=models.DurationField())),
  610. ),
  611. )
  612. self.assertQuerysetEqual(
  613. CaseTestModel.objects.all().order_by('pk'),
  614. [(1, timedelta(1)), (2, timedelta(2)), (3, None), (2, timedelta(2)), (3, None), (3, None), (4, None)],
  615. transform=attrgetter('integer', 'duration')
  616. )
  617. def test_update_email(self):
  618. CaseTestModel.objects.update(
  619. email=Case(
  620. When(integer=1, then=Value('1@example.com')),
  621. When(integer=2, then=Value('2@example.com')),
  622. default=Value(''),
  623. ),
  624. )
  625. self.assertQuerysetEqual(
  626. CaseTestModel.objects.all().order_by('pk'),
  627. [(1, '1@example.com'), (2, '2@example.com'), (3, ''), (2, '2@example.com'), (3, ''), (3, ''), (4, '')],
  628. transform=attrgetter('integer', 'email')
  629. )
  630. def test_update_file(self):
  631. CaseTestModel.objects.update(
  632. file=Case(
  633. When(integer=1, then=Value('~/1')),
  634. When(integer=2, then=Value('~/2')),
  635. ),
  636. )
  637. self.assertQuerysetEqual(
  638. CaseTestModel.objects.all().order_by('pk'),
  639. [(1, '~/1'), (2, '~/2'), (3, ''), (2, '~/2'), (3, ''), (3, ''), (4, '')],
  640. transform=lambda o: (o.integer, six.text_type(o.file))
  641. )
  642. def test_update_file_path(self):
  643. CaseTestModel.objects.update(
  644. file_path=Case(
  645. When(integer=1, then=Value('~/1')),
  646. When(integer=2, then=Value('~/2')),
  647. default=Value(''),
  648. ),
  649. )
  650. self.assertQuerysetEqual(
  651. CaseTestModel.objects.all().order_by('pk'),
  652. [(1, '~/1'), (2, '~/2'), (3, ''), (2, '~/2'), (3, ''), (3, ''), (4, '')],
  653. transform=attrgetter('integer', 'file_path')
  654. )
  655. def test_update_float(self):
  656. CaseTestModel.objects.update(
  657. float=Case(
  658. When(integer=1, then=Value(1.1)),
  659. When(integer=2, then=Value(2.2)),
  660. ),
  661. )
  662. self.assertQuerysetEqual(
  663. CaseTestModel.objects.all().order_by('pk'),
  664. [(1, 1.1), (2, 2.2), (3, None), (2, 2.2), (3, None), (3, None), (4, None)],
  665. transform=attrgetter('integer', 'float')
  666. )
  667. def test_update_image(self):
  668. CaseTestModel.objects.update(
  669. image=Case(
  670. When(integer=1, then=Value('~/1')),
  671. When(integer=2, then=Value('~/2')),
  672. ),
  673. )
  674. self.assertQuerysetEqual(
  675. CaseTestModel.objects.all().order_by('pk'),
  676. [(1, '~/1'), (2, '~/2'), (3, ''), (2, '~/2'), (3, ''), (3, ''), (4, '')],
  677. transform=lambda o: (o.integer, six.text_type(o.image))
  678. )
  679. def test_update_ip_address(self):
  680. CaseTestModel.objects.update(
  681. ip_address=Case(
  682. # fails on postgresql if output_field is not set explicitly
  683. When(integer=1, then=Value('1.1.1.1')),
  684. When(integer=2, then=Value('2.2.2.2')),
  685. output_field=models.IPAddressField(),
  686. ),
  687. )
  688. self.assertQuerysetEqual(
  689. CaseTestModel.objects.all().order_by('pk'),
  690. [(1, '1.1.1.1'), (2, '2.2.2.2'), (3, None), (2, '2.2.2.2'), (3, None), (3, None), (4, None)],
  691. transform=attrgetter('integer', 'ip_address')
  692. )
  693. def test_update_generic_ip_address(self):
  694. CaseTestModel.objects.update(
  695. generic_ip_address=Case(
  696. # fails on postgresql if output_field is not set explicitly
  697. When(integer=1, then=Value('1.1.1.1')),
  698. When(integer=2, then=Value('2.2.2.2')),
  699. output_field=models.GenericIPAddressField(),
  700. ),
  701. )
  702. self.assertQuerysetEqual(
  703. CaseTestModel.objects.all().order_by('pk'),
  704. [(1, '1.1.1.1'), (2, '2.2.2.2'), (3, None), (2, '2.2.2.2'), (3, None), (3, None), (4, None)],
  705. transform=attrgetter('integer', 'generic_ip_address')
  706. )
  707. def test_update_null_boolean(self):
  708. CaseTestModel.objects.update(
  709. null_boolean=Case(
  710. When(integer=1, then=Value(True)),
  711. When(integer=2, then=Value(False)),
  712. ),
  713. )
  714. self.assertQuerysetEqual(
  715. CaseTestModel.objects.all().order_by('pk'),
  716. [(1, True), (2, False), (3, None), (2, False), (3, None), (3, None), (4, None)],
  717. transform=attrgetter('integer', 'null_boolean')
  718. )
  719. def test_update_positive_integer(self):
  720. CaseTestModel.objects.update(
  721. positive_integer=Case(
  722. When(integer=1, then=Value(1)),
  723. When(integer=2, then=Value(2)),
  724. ),
  725. )
  726. self.assertQuerysetEqual(
  727. CaseTestModel.objects.all().order_by('pk'),
  728. [(1, 1), (2, 2), (3, None), (2, 2), (3, None), (3, None), (4, None)],
  729. transform=attrgetter('integer', 'positive_integer')
  730. )
  731. def test_update_positive_small_integer(self):
  732. CaseTestModel.objects.update(
  733. positive_small_integer=Case(
  734. When(integer=1, then=Value(1)),
  735. When(integer=2, then=Value(2)),
  736. ),
  737. )
  738. self.assertQuerysetEqual(
  739. CaseTestModel.objects.all().order_by('pk'),
  740. [(1, 1), (2, 2), (3, None), (2, 2), (3, None), (3, None), (4, None)],
  741. transform=attrgetter('integer', 'positive_small_integer')
  742. )
  743. def test_update_slug(self):
  744. CaseTestModel.objects.update(
  745. slug=Case(
  746. When(integer=1, then=Value('1')),
  747. When(integer=2, then=Value('2')),
  748. default=Value(''),
  749. ),
  750. )
  751. self.assertQuerysetEqual(
  752. CaseTestModel.objects.all().order_by('pk'),
  753. [(1, '1'), (2, '2'), (3, ''), (2, '2'), (3, ''), (3, ''), (4, '')],
  754. transform=attrgetter('integer', 'slug')
  755. )
  756. def test_update_small_integer(self):
  757. CaseTestModel.objects.update(
  758. small_integer=Case(
  759. When(integer=1, then=Value(1)),
  760. When(integer=2, then=Value(2)),
  761. ),
  762. )
  763. self.assertQuerysetEqual(
  764. CaseTestModel.objects.all().order_by('pk'),
  765. [(1, 1), (2, 2), (3, None), (2, 2), (3, None), (3, None), (4, None)],
  766. transform=attrgetter('integer', 'small_integer')
  767. )
  768. def test_update_string(self):
  769. CaseTestModel.objects.filter(string__in=['1', '2']).update(
  770. string=Case(
  771. When(integer=1, then=Value('1', output_field=models.CharField())),
  772. When(integer=2, then=Value('2', output_field=models.CharField())),
  773. ),
  774. )
  775. self.assertQuerysetEqual(
  776. CaseTestModel.objects.filter(string__in=['1', '2']).order_by('pk'),
  777. [(1, '1'), (2, '2'), (2, '2')],
  778. transform=attrgetter('integer', 'string')
  779. )
  780. def test_update_text(self):
  781. CaseTestModel.objects.update(
  782. text=Case(
  783. When(integer=1, then=Value('1')),
  784. When(integer=2, then=Value('2')),
  785. default=Value(''),
  786. ),
  787. )
  788. self.assertQuerysetEqual(
  789. CaseTestModel.objects.all().order_by('pk'),
  790. [(1, '1'), (2, '2'), (3, ''), (2, '2'), (3, ''), (3, ''), (4, '')],
  791. transform=attrgetter('integer', 'text')
  792. )
  793. def test_update_time(self):
  794. CaseTestModel.objects.update(
  795. time=Case(
  796. # fails on sqlite if output_field is not set explicitly on all
  797. # Values containing times
  798. When(integer=1, then=Value(time(1), output_field=models.TimeField())),
  799. When(integer=2, then=Value(time(2), output_field=models.TimeField())),
  800. ),
  801. )
  802. self.assertQuerysetEqual(
  803. CaseTestModel.objects.all().order_by('pk'),
  804. [(1, time(1)), (2, time(2)), (3, None), (2, time(2)), (3, None), (3, None), (4, None)],
  805. transform=attrgetter('integer', 'time')
  806. )
  807. def test_update_url(self):
  808. CaseTestModel.objects.update(
  809. url=Case(
  810. When(integer=1, then=Value('http://1.example.com/')),
  811. When(integer=2, then=Value('http://2.example.com/')),
  812. default=Value(''),
  813. ),
  814. )
  815. self.assertQuerysetEqual(
  816. CaseTestModel.objects.all().order_by('pk'),
  817. [
  818. (1, 'http://1.example.com/'), (2, 'http://2.example.com/'), (3, ''), (2, 'http://2.example.com/'),
  819. (3, ''), (3, ''), (4, '')
  820. ],
  821. transform=attrgetter('integer', 'url')
  822. )
  823. def test_update_uuid(self):
  824. CaseTestModel.objects.update(
  825. uuid=Case(
  826. # fails on sqlite if output_field is not set explicitly on all
  827. # Values containing UUIDs
  828. When(integer=1, then=Value(
  829. UUID('11111111111111111111111111111111'),
  830. output_field=models.UUIDField(),
  831. )),
  832. When(integer=2, then=Value(
  833. UUID('22222222222222222222222222222222'),
  834. output_field=models.UUIDField(),
  835. )),
  836. ),
  837. )
  838. self.assertQuerysetEqual(
  839. CaseTestModel.objects.all().order_by('pk'),
  840. [
  841. (1, UUID('11111111111111111111111111111111')), (2, UUID('22222222222222222222222222222222')), (3, None),
  842. (2, UUID('22222222222222222222222222222222')), (3, None), (3, None), (4, None)
  843. ],
  844. transform=attrgetter('integer', 'uuid')
  845. )
  846. def test_update_fk(self):
  847. obj1, obj2 = CaseTestModel.objects.all()[:2]
  848. CaseTestModel.objects.update(
  849. fk=Case(
  850. When(integer=1, then=Value(obj1.pk)),
  851. When(integer=2, then=Value(obj2.pk)),
  852. ),
  853. )
  854. self.assertQuerysetEqual(
  855. CaseTestModel.objects.all().order_by('pk'),
  856. [(1, obj1.pk), (2, obj2.pk), (3, None), (2, obj2.pk), (3, None), (3, None), (4, None)],
  857. transform=attrgetter('integer', 'fk_id')
  858. )
  859. def test_lookup_in_condition(self):
  860. self.assertQuerysetEqual(
  861. CaseTestModel.objects.annotate(
  862. test=Case(
  863. When(integer__lt=2, then=Value('less than 2')),
  864. When(integer__gt=2, then=Value('greater than 2')),
  865. default=Value('equal to 2'),
  866. output_field=models.CharField(),
  867. ),
  868. ).order_by('pk'),
  869. [
  870. (1, 'less than 2'), (2, 'equal to 2'), (3, 'greater than 2'), (2, 'equal to 2'), (3, 'greater than 2'),
  871. (3, 'greater than 2'), (4, 'greater than 2')
  872. ],
  873. transform=attrgetter('integer', 'test')
  874. )
  875. def test_lookup_different_fields(self):
  876. self.assertQuerysetEqual(
  877. CaseTestModel.objects.annotate(
  878. test=Case(
  879. When(integer=2, integer2=3, then=Value('when')),
  880. default=Value('default'),
  881. output_field=models.CharField(),
  882. ),
  883. ).order_by('pk'),
  884. [
  885. (1, 1, 'default'), (2, 3, 'when'), (3, 4, 'default'), (2, 2, 'default'), (3, 4, 'default'),
  886. (3, 3, 'default'), (4, 5, 'default')
  887. ],
  888. transform=attrgetter('integer', 'integer2', 'test')
  889. )
  890. def test_combined_q_object(self):
  891. self.assertQuerysetEqual(
  892. CaseTestModel.objects.annotate(
  893. test=Case(
  894. When(Q(integer=2) | Q(integer2=3), then=Value('when')),
  895. default=Value('default'),
  896. output_field=models.CharField(),
  897. ),
  898. ).order_by('pk'),
  899. [
  900. (1, 1, 'default'), (2, 3, 'when'), (3, 4, 'default'), (2, 2, 'when'), (3, 4, 'default'),
  901. (3, 3, 'when'), (4, 5, 'default')
  902. ],
  903. transform=attrgetter('integer', 'integer2', 'test')
  904. )
  905. class CaseDocumentationExamples(TestCase):
  906. @classmethod
  907. def setUpTestData(cls):
  908. Client.objects.create(
  909. name='Jane Doe',
  910. account_type=Client.REGULAR,
  911. registered_on=date.today() - timedelta(days=36),
  912. )
  913. Client.objects.create(
  914. name='James Smith',
  915. account_type=Client.GOLD,
  916. registered_on=date.today() - timedelta(days=5),
  917. )
  918. Client.objects.create(
  919. name='Jack Black',
  920. account_type=Client.PLATINUM,
  921. registered_on=date.today() - timedelta(days=10 * 365),
  922. )
  923. def test_simple_example(self):
  924. self.assertQuerysetEqual(
  925. Client.objects.annotate(
  926. discount=Case(
  927. When(account_type=Client.GOLD, then=Value('5%')),
  928. When(account_type=Client.PLATINUM, then=Value('10%')),
  929. default=Value('0%'),
  930. output_field=models.CharField(),
  931. ),
  932. ).order_by('pk'),
  933. [('Jane Doe', '0%'), ('James Smith', '5%'), ('Jack Black', '10%')],
  934. transform=attrgetter('name', 'discount')
  935. )
  936. def test_lookup_example(self):
  937. a_month_ago = date.today() - timedelta(days=30)
  938. a_year_ago = date.today() - timedelta(days=365)
  939. self.assertQuerysetEqual(
  940. Client.objects.annotate(
  941. discount=Case(
  942. When(registered_on__lte=a_year_ago, then=Value('10%')),
  943. When(registered_on__lte=a_month_ago, then=Value('5%')),
  944. default=Value('0%'),
  945. output_field=models.CharField(),
  946. ),
  947. ).order_by('pk'),
  948. [('Jane Doe', '5%'), ('James Smith', '0%'), ('Jack Black', '10%')],
  949. transform=attrgetter('name', 'discount')
  950. )
  951. def test_conditional_update_example(self):
  952. a_month_ago = date.today() - timedelta(days=30)
  953. a_year_ago = date.today() - timedelta(days=365)
  954. Client.objects.update(
  955. account_type=Case(
  956. When(registered_on__lte=a_year_ago, then=Value(Client.PLATINUM)),
  957. When(registered_on__lte=a_month_ago, then=Value(Client.GOLD)),
  958. default=Value(Client.REGULAR),
  959. ),
  960. )
  961. self.assertQuerysetEqual(
  962. Client.objects.all().order_by('pk'),
  963. [('Jane Doe', 'G'), ('James Smith', 'R'), ('Jack Black', 'P')],
  964. transform=attrgetter('name', 'account_type')
  965. )
  966. def test_conditional_aggregation_example(self):
  967. Client.objects.create(
  968. name='Jean Grey',
  969. account_type=Client.REGULAR,
  970. registered_on=date.today(),
  971. )
  972. Client.objects.create(
  973. name='James Bond',
  974. account_type=Client.PLATINUM,
  975. registered_on=date.today(),
  976. )
  977. Client.objects.create(
  978. name='Jane Porter',
  979. account_type=Client.PLATINUM,
  980. registered_on=date.today(),
  981. )
  982. self.assertEqual(
  983. Client.objects.aggregate(
  984. regular=models.Sum(Case(
  985. When(account_type=Client.REGULAR, then=Value(1)),
  986. output_field=models.IntegerField(),
  987. )),
  988. gold=models.Sum(Case(
  989. When(account_type=Client.GOLD, then=Value(1)),
  990. output_field=models.IntegerField(),
  991. )),
  992. platinum=models.Sum(Case(
  993. When(account_type=Client.PLATINUM, then=Value(1)),
  994. output_field=models.IntegerField(),
  995. )),
  996. ),
  997. {'regular': 2, 'gold': 1, 'platinum': 3}
  998. )