tests.py 42 KB

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