tests.py 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664
  1. import unittest
  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 connection
  8. from django.db.models import (
  9. BinaryField,
  10. BooleanField,
  11. Case,
  12. Count,
  13. DecimalField,
  14. F,
  15. GenericIPAddressField,
  16. IntegerField,
  17. Max,
  18. Min,
  19. Q,
  20. Sum,
  21. TextField,
  22. Value,
  23. When,
  24. )
  25. from django.test import SimpleTestCase, TestCase
  26. from .models import CaseTestModel, Client, FKCaseTestModel, O2OCaseTestModel
  27. try:
  28. from PIL import Image
  29. except ImportError:
  30. Image = None
  31. class CaseExpressionTests(TestCase):
  32. @classmethod
  33. def setUpTestData(cls):
  34. o = CaseTestModel.objects.create(integer=1, integer2=1, string="1")
  35. O2OCaseTestModel.objects.create(o2o=o, integer=1)
  36. FKCaseTestModel.objects.create(fk=o, integer=1)
  37. o = CaseTestModel.objects.create(integer=2, integer2=3, string="2")
  38. O2OCaseTestModel.objects.create(o2o=o, integer=2)
  39. FKCaseTestModel.objects.create(fk=o, integer=2)
  40. FKCaseTestModel.objects.create(fk=o, integer=3)
  41. o = CaseTestModel.objects.create(integer=3, integer2=4, string="3")
  42. O2OCaseTestModel.objects.create(o2o=o, integer=3)
  43. FKCaseTestModel.objects.create(fk=o, integer=3)
  44. FKCaseTestModel.objects.create(fk=o, integer=4)
  45. o = CaseTestModel.objects.create(integer=2, integer2=2, string="2")
  46. O2OCaseTestModel.objects.create(o2o=o, integer=2)
  47. FKCaseTestModel.objects.create(fk=o, integer=2)
  48. FKCaseTestModel.objects.create(fk=o, integer=3)
  49. o = CaseTestModel.objects.create(integer=3, integer2=4, string="3")
  50. O2OCaseTestModel.objects.create(o2o=o, integer=3)
  51. FKCaseTestModel.objects.create(fk=o, integer=3)
  52. FKCaseTestModel.objects.create(fk=o, integer=4)
  53. o = CaseTestModel.objects.create(integer=3, integer2=3, string="3")
  54. O2OCaseTestModel.objects.create(o2o=o, integer=3)
  55. FKCaseTestModel.objects.create(fk=o, integer=3)
  56. FKCaseTestModel.objects.create(fk=o, integer=4)
  57. o = CaseTestModel.objects.create(integer=4, integer2=5, string="4")
  58. O2OCaseTestModel.objects.create(o2o=o, integer=1)
  59. FKCaseTestModel.objects.create(fk=o, integer=5)
  60. cls.group_by_fields = [
  61. f.name
  62. for f in CaseTestModel._meta.get_fields()
  63. if not (f.is_relation and f.auto_created)
  64. and (
  65. connection.features.allows_group_by_lob
  66. or not isinstance(f, (BinaryField, TextField))
  67. )
  68. ]
  69. def test_annotate(self):
  70. self.assertQuerysetEqual(
  71. CaseTestModel.objects.annotate(
  72. test=Case(
  73. When(integer=1, then=Value("one")),
  74. When(integer=2, then=Value("two")),
  75. default=Value("other"),
  76. )
  77. ).order_by("pk"),
  78. [
  79. (1, "one"),
  80. (2, "two"),
  81. (3, "other"),
  82. (2, "two"),
  83. (3, "other"),
  84. (3, "other"),
  85. (4, "other"),
  86. ],
  87. transform=attrgetter("integer", "test"),
  88. )
  89. def test_annotate_without_default(self):
  90. self.assertQuerysetEqual(
  91. CaseTestModel.objects.annotate(
  92. test=Case(
  93. When(integer=1, then=1),
  94. When(integer=2, then=2),
  95. )
  96. ).order_by("pk"),
  97. [(1, 1), (2, 2), (3, None), (2, 2), (3, None), (3, None), (4, None)],
  98. transform=attrgetter("integer", "test"),
  99. )
  100. def test_annotate_with_expression_as_value(self):
  101. self.assertQuerysetEqual(
  102. CaseTestModel.objects.annotate(
  103. f_test=Case(
  104. When(integer=1, then=F("integer") + 1),
  105. When(integer=2, then=F("integer") + 3),
  106. default="integer",
  107. )
  108. ).order_by("pk"),
  109. [(1, 2), (2, 5), (3, 3), (2, 5), (3, 3), (3, 3), (4, 4)],
  110. transform=attrgetter("integer", "f_test"),
  111. )
  112. def test_annotate_with_expression_as_condition(self):
  113. self.assertQuerysetEqual(
  114. CaseTestModel.objects.annotate(
  115. f_test=Case(
  116. When(integer2=F("integer"), then=Value("equal")),
  117. When(integer2=F("integer") + 1, then=Value("+1")),
  118. )
  119. ).order_by("pk"),
  120. [
  121. (1, "equal"),
  122. (2, "+1"),
  123. (3, "+1"),
  124. (2, "equal"),
  125. (3, "+1"),
  126. (3, "equal"),
  127. (4, "+1"),
  128. ],
  129. transform=attrgetter("integer", "f_test"),
  130. )
  131. def test_annotate_with_join_in_value(self):
  132. self.assertQuerysetEqual(
  133. CaseTestModel.objects.annotate(
  134. join_test=Case(
  135. When(integer=1, then=F("o2o_rel__integer") + 1),
  136. When(integer=2, then=F("o2o_rel__integer") + 3),
  137. default="o2o_rel__integer",
  138. )
  139. ).order_by("pk"),
  140. [(1, 2), (2, 5), (3, 3), (2, 5), (3, 3), (3, 3), (4, 1)],
  141. transform=attrgetter("integer", "join_test"),
  142. )
  143. def test_annotate_with_in_clause(self):
  144. fk_rels = FKCaseTestModel.objects.filter(integer__in=[5])
  145. self.assertQuerysetEqual(
  146. CaseTestModel.objects.only("pk", "integer")
  147. .annotate(
  148. in_test=Sum(
  149. Case(
  150. When(fk_rel__in=fk_rels, then=F("fk_rel__integer")),
  151. default=Value(0),
  152. )
  153. )
  154. )
  155. .order_by("pk"),
  156. [(1, 0), (2, 0), (3, 0), (2, 0), (3, 0), (3, 0), (4, 5)],
  157. transform=attrgetter("integer", "in_test"),
  158. )
  159. def test_annotate_with_join_in_condition(self):
  160. self.assertQuerysetEqual(
  161. CaseTestModel.objects.annotate(
  162. join_test=Case(
  163. When(integer2=F("o2o_rel__integer"), then=Value("equal")),
  164. When(integer2=F("o2o_rel__integer") + 1, then=Value("+1")),
  165. default=Value("other"),
  166. )
  167. ).order_by("pk"),
  168. [
  169. (1, "equal"),
  170. (2, "+1"),
  171. (3, "+1"),
  172. (2, "equal"),
  173. (3, "+1"),
  174. (3, "equal"),
  175. (4, "other"),
  176. ],
  177. transform=attrgetter("integer", "join_test"),
  178. )
  179. def test_annotate_with_join_in_predicate(self):
  180. self.assertQuerysetEqual(
  181. CaseTestModel.objects.annotate(
  182. join_test=Case(
  183. When(o2o_rel__integer=1, then=Value("one")),
  184. When(o2o_rel__integer=2, then=Value("two")),
  185. When(o2o_rel__integer=3, then=Value("three")),
  186. default=Value("other"),
  187. )
  188. ).order_by("pk"),
  189. [
  190. (1, "one"),
  191. (2, "two"),
  192. (3, "three"),
  193. (2, "two"),
  194. (3, "three"),
  195. (3, "three"),
  196. (4, "one"),
  197. ],
  198. transform=attrgetter("integer", "join_test"),
  199. )
  200. def test_annotate_with_annotation_in_value(self):
  201. self.assertQuerysetEqual(
  202. CaseTestModel.objects.annotate(
  203. f_plus_1=F("integer") + 1,
  204. f_plus_3=F("integer") + 3,
  205. )
  206. .annotate(
  207. f_test=Case(
  208. When(integer=1, then="f_plus_1"),
  209. When(integer=2, then="f_plus_3"),
  210. default="integer",
  211. ),
  212. )
  213. .order_by("pk"),
  214. [(1, 2), (2, 5), (3, 3), (2, 5), (3, 3), (3, 3), (4, 4)],
  215. transform=attrgetter("integer", "f_test"),
  216. )
  217. def test_annotate_with_annotation_in_condition(self):
  218. self.assertQuerysetEqual(
  219. CaseTestModel.objects.annotate(
  220. f_plus_1=F("integer") + 1,
  221. )
  222. .annotate(
  223. f_test=Case(
  224. When(integer2=F("integer"), then=Value("equal")),
  225. When(integer2=F("f_plus_1"), then=Value("+1")),
  226. ),
  227. )
  228. .order_by("pk"),
  229. [
  230. (1, "equal"),
  231. (2, "+1"),
  232. (3, "+1"),
  233. (2, "equal"),
  234. (3, "+1"),
  235. (3, "equal"),
  236. (4, "+1"),
  237. ],
  238. transform=attrgetter("integer", "f_test"),
  239. )
  240. def test_annotate_with_annotation_in_predicate(self):
  241. self.assertQuerysetEqual(
  242. CaseTestModel.objects.annotate(
  243. f_minus_2=F("integer") - 2,
  244. )
  245. .annotate(
  246. test=Case(
  247. When(f_minus_2=-1, then=Value("negative one")),
  248. When(f_minus_2=0, then=Value("zero")),
  249. When(f_minus_2=1, then=Value("one")),
  250. default=Value("other"),
  251. ),
  252. )
  253. .order_by("pk"),
  254. [
  255. (1, "negative one"),
  256. (2, "zero"),
  257. (3, "one"),
  258. (2, "zero"),
  259. (3, "one"),
  260. (3, "one"),
  261. (4, "other"),
  262. ],
  263. transform=attrgetter("integer", "test"),
  264. )
  265. def test_annotate_with_aggregation_in_value(self):
  266. self.assertQuerysetEqual(
  267. CaseTestModel.objects.values(*self.group_by_fields)
  268. .annotate(
  269. min=Min("fk_rel__integer"),
  270. max=Max("fk_rel__integer"),
  271. )
  272. .annotate(
  273. test=Case(
  274. When(integer=2, then="min"),
  275. When(integer=3, then="max"),
  276. ),
  277. )
  278. .order_by("pk"),
  279. [
  280. (1, None, 1, 1),
  281. (2, 2, 2, 3),
  282. (3, 4, 3, 4),
  283. (2, 2, 2, 3),
  284. (3, 4, 3, 4),
  285. (3, 4, 3, 4),
  286. (4, None, 5, 5),
  287. ],
  288. transform=itemgetter("integer", "test", "min", "max"),
  289. )
  290. def test_annotate_with_aggregation_in_condition(self):
  291. self.assertQuerysetEqual(
  292. CaseTestModel.objects.values(*self.group_by_fields)
  293. .annotate(
  294. min=Min("fk_rel__integer"),
  295. max=Max("fk_rel__integer"),
  296. )
  297. .annotate(
  298. test=Case(
  299. When(integer2=F("min"), then=Value("min")),
  300. When(integer2=F("max"), then=Value("max")),
  301. ),
  302. )
  303. .order_by("pk"),
  304. [
  305. (1, 1, "min"),
  306. (2, 3, "max"),
  307. (3, 4, "max"),
  308. (2, 2, "min"),
  309. (3, 4, "max"),
  310. (3, 3, "min"),
  311. (4, 5, "min"),
  312. ],
  313. transform=itemgetter("integer", "integer2", "test"),
  314. )
  315. def test_annotate_with_aggregation_in_predicate(self):
  316. self.assertQuerysetEqual(
  317. CaseTestModel.objects.values(*self.group_by_fields)
  318. .annotate(
  319. max=Max("fk_rel__integer"),
  320. )
  321. .annotate(
  322. test=Case(
  323. When(max=3, then=Value("max = 3")),
  324. When(max=4, then=Value("max = 4")),
  325. default=Value(""),
  326. ),
  327. )
  328. .order_by("pk"),
  329. [
  330. (1, 1, ""),
  331. (2, 3, "max = 3"),
  332. (3, 4, "max = 4"),
  333. (2, 3, "max = 3"),
  334. (3, 4, "max = 4"),
  335. (3, 4, "max = 4"),
  336. (4, 5, ""),
  337. ],
  338. transform=itemgetter("integer", "max", "test"),
  339. )
  340. def test_annotate_exclude(self):
  341. self.assertQuerysetEqual(
  342. CaseTestModel.objects.annotate(
  343. test=Case(
  344. When(integer=1, then=Value("one")),
  345. When(integer=2, then=Value("two")),
  346. default=Value("other"),
  347. )
  348. )
  349. .exclude(test="other")
  350. .order_by("pk"),
  351. [(1, "one"), (2, "two"), (2, "two")],
  352. transform=attrgetter("integer", "test"),
  353. )
  354. def test_annotate_filter_decimal(self):
  355. obj = CaseTestModel.objects.create(integer=0, decimal=Decimal("1"))
  356. qs = CaseTestModel.objects.annotate(
  357. x=Case(When(integer=0, then=F("decimal"))),
  358. y=Case(When(integer=0, then=Value(Decimal("1")))),
  359. )
  360. self.assertSequenceEqual(qs.filter(Q(x=1) & Q(x=Decimal("1"))), [obj])
  361. self.assertSequenceEqual(qs.filter(Q(y=1) & Q(y=Decimal("1"))), [obj])
  362. def test_annotate_values_not_in_order_by(self):
  363. self.assertEqual(
  364. list(
  365. CaseTestModel.objects.annotate(
  366. test=Case(
  367. When(integer=1, then=Value("one")),
  368. When(integer=2, then=Value("two")),
  369. When(integer=3, then=Value("three")),
  370. default=Value("other"),
  371. )
  372. )
  373. .order_by("test")
  374. .values_list("integer", flat=True)
  375. ),
  376. [1, 4, 3, 3, 3, 2, 2],
  377. )
  378. def test_annotate_with_empty_when(self):
  379. objects = CaseTestModel.objects.annotate(
  380. selected=Case(
  381. When(pk__in=[], then=Value("selected")),
  382. default=Value("not selected"),
  383. )
  384. )
  385. self.assertEqual(len(objects), CaseTestModel.objects.count())
  386. self.assertTrue(all(obj.selected == "not selected" for obj in objects))
  387. def test_combined_expression(self):
  388. self.assertQuerysetEqual(
  389. CaseTestModel.objects.annotate(
  390. test=Case(
  391. When(integer=1, then=2),
  392. When(integer=2, then=1),
  393. default=3,
  394. )
  395. + 1,
  396. ).order_by("pk"),
  397. [(1, 3), (2, 2), (3, 4), (2, 2), (3, 4), (3, 4), (4, 4)],
  398. transform=attrgetter("integer", "test"),
  399. )
  400. def test_in_subquery(self):
  401. self.assertQuerysetEqual(
  402. CaseTestModel.objects.filter(
  403. pk__in=CaseTestModel.objects.annotate(
  404. test=Case(
  405. When(integer=F("integer2"), then="pk"),
  406. When(integer=4, then="pk"),
  407. ),
  408. ).values("test")
  409. ).order_by("pk"),
  410. [(1, 1), (2, 2), (3, 3), (4, 5)],
  411. transform=attrgetter("integer", "integer2"),
  412. )
  413. def test_condition_with_lookups(self):
  414. qs = CaseTestModel.objects.annotate(
  415. test=Case(
  416. When(Q(integer2=1), string="2", then=Value(False)),
  417. When(Q(integer2=1), string="1", then=Value(True)),
  418. default=Value(False),
  419. output_field=BooleanField(),
  420. ),
  421. )
  422. self.assertIs(qs.get(integer=1).test, True)
  423. def test_case_reuse(self):
  424. SOME_CASE = Case(
  425. When(pk=0, then=Value("0")),
  426. default=Value("1"),
  427. )
  428. self.assertQuerysetEqual(
  429. CaseTestModel.objects.annotate(somecase=SOME_CASE).order_by("pk"),
  430. CaseTestModel.objects.annotate(somecase=SOME_CASE)
  431. .order_by("pk")
  432. .values_list("pk", "somecase"),
  433. lambda x: (x.pk, x.somecase),
  434. )
  435. def test_aggregate(self):
  436. self.assertEqual(
  437. CaseTestModel.objects.aggregate(
  438. one=Sum(
  439. Case(
  440. When(integer=1, then=1),
  441. )
  442. ),
  443. two=Sum(
  444. Case(
  445. When(integer=2, then=1),
  446. )
  447. ),
  448. three=Sum(
  449. Case(
  450. When(integer=3, then=1),
  451. )
  452. ),
  453. four=Sum(
  454. Case(
  455. When(integer=4, then=1),
  456. )
  457. ),
  458. ),
  459. {"one": 1, "two": 2, "three": 3, "four": 1},
  460. )
  461. def test_aggregate_with_expression_as_value(self):
  462. self.assertEqual(
  463. CaseTestModel.objects.aggregate(
  464. one=Sum(Case(When(integer=1, then="integer"))),
  465. two=Sum(Case(When(integer=2, then=F("integer") - 1))),
  466. three=Sum(Case(When(integer=3, then=F("integer") + 1))),
  467. ),
  468. {"one": 1, "two": 2, "three": 12},
  469. )
  470. def test_aggregate_with_expression_as_condition(self):
  471. self.assertEqual(
  472. CaseTestModel.objects.aggregate(
  473. equal=Sum(
  474. Case(
  475. When(integer2=F("integer"), then=1),
  476. )
  477. ),
  478. plus_one=Sum(
  479. Case(
  480. When(integer2=F("integer") + 1, then=1),
  481. )
  482. ),
  483. ),
  484. {"equal": 3, "plus_one": 4},
  485. )
  486. def test_filter(self):
  487. self.assertQuerysetEqual(
  488. CaseTestModel.objects.filter(
  489. integer2=Case(
  490. When(integer=2, then=3),
  491. When(integer=3, then=4),
  492. default=1,
  493. )
  494. ).order_by("pk"),
  495. [(1, 1), (2, 3), (3, 4), (3, 4)],
  496. transform=attrgetter("integer", "integer2"),
  497. )
  498. def test_filter_without_default(self):
  499. self.assertQuerysetEqual(
  500. CaseTestModel.objects.filter(
  501. integer2=Case(
  502. When(integer=2, then=3),
  503. When(integer=3, then=4),
  504. )
  505. ).order_by("pk"),
  506. [(2, 3), (3, 4), (3, 4)],
  507. transform=attrgetter("integer", "integer2"),
  508. )
  509. def test_filter_with_expression_as_value(self):
  510. self.assertQuerysetEqual(
  511. CaseTestModel.objects.filter(
  512. integer2=Case(
  513. When(integer=2, then=F("integer") + 1),
  514. When(integer=3, then=F("integer")),
  515. default="integer",
  516. )
  517. ).order_by("pk"),
  518. [(1, 1), (2, 3), (3, 3)],
  519. transform=attrgetter("integer", "integer2"),
  520. )
  521. def test_filter_with_expression_as_condition(self):
  522. self.assertQuerysetEqual(
  523. CaseTestModel.objects.filter(
  524. string=Case(
  525. When(integer2=F("integer"), then=Value("2")),
  526. When(integer2=F("integer") + 1, then=Value("3")),
  527. )
  528. ).order_by("pk"),
  529. [(3, 4, "3"), (2, 2, "2"), (3, 4, "3")],
  530. transform=attrgetter("integer", "integer2", "string"),
  531. )
  532. def test_filter_with_join_in_value(self):
  533. self.assertQuerysetEqual(
  534. CaseTestModel.objects.filter(
  535. integer2=Case(
  536. When(integer=2, then=F("o2o_rel__integer") + 1),
  537. When(integer=3, then=F("o2o_rel__integer")),
  538. default="o2o_rel__integer",
  539. )
  540. ).order_by("pk"),
  541. [(1, 1), (2, 3), (3, 3)],
  542. transform=attrgetter("integer", "integer2"),
  543. )
  544. def test_filter_with_join_in_condition(self):
  545. self.assertQuerysetEqual(
  546. CaseTestModel.objects.filter(
  547. integer=Case(
  548. When(integer2=F("o2o_rel__integer") + 1, then=2),
  549. When(integer2=F("o2o_rel__integer"), then=3),
  550. )
  551. ).order_by("pk"),
  552. [(2, 3), (3, 3)],
  553. transform=attrgetter("integer", "integer2"),
  554. )
  555. def test_filter_with_join_in_predicate(self):
  556. self.assertQuerysetEqual(
  557. CaseTestModel.objects.filter(
  558. integer2=Case(
  559. When(o2o_rel__integer=1, then=1),
  560. When(o2o_rel__integer=2, then=3),
  561. When(o2o_rel__integer=3, then=4),
  562. )
  563. ).order_by("pk"),
  564. [(1, 1), (2, 3), (3, 4), (3, 4)],
  565. transform=attrgetter("integer", "integer2"),
  566. )
  567. def test_filter_with_annotation_in_value(self):
  568. self.assertQuerysetEqual(
  569. CaseTestModel.objects.annotate(
  570. f=F("integer"),
  571. f_plus_1=F("integer") + 1,
  572. )
  573. .filter(
  574. integer2=Case(
  575. When(integer=2, then="f_plus_1"),
  576. When(integer=3, then="f"),
  577. ),
  578. )
  579. .order_by("pk"),
  580. [(2, 3), (3, 3)],
  581. transform=attrgetter("integer", "integer2"),
  582. )
  583. def test_filter_with_annotation_in_condition(self):
  584. self.assertQuerysetEqual(
  585. CaseTestModel.objects.annotate(
  586. f_plus_1=F("integer") + 1,
  587. )
  588. .filter(
  589. integer=Case(
  590. When(integer2=F("integer"), then=2),
  591. When(integer2=F("f_plus_1"), then=3),
  592. ),
  593. )
  594. .order_by("pk"),
  595. [(3, 4), (2, 2), (3, 4)],
  596. transform=attrgetter("integer", "integer2"),
  597. )
  598. def test_filter_with_annotation_in_predicate(self):
  599. self.assertQuerysetEqual(
  600. CaseTestModel.objects.annotate(
  601. f_plus_1=F("integer") + 1,
  602. )
  603. .filter(
  604. integer2=Case(
  605. When(f_plus_1=3, then=3),
  606. When(f_plus_1=4, then=4),
  607. default=1,
  608. ),
  609. )
  610. .order_by("pk"),
  611. [(1, 1), (2, 3), (3, 4), (3, 4)],
  612. transform=attrgetter("integer", "integer2"),
  613. )
  614. def test_filter_with_aggregation_in_value(self):
  615. self.assertQuerysetEqual(
  616. CaseTestModel.objects.values(*self.group_by_fields)
  617. .annotate(
  618. min=Min("fk_rel__integer"),
  619. max=Max("fk_rel__integer"),
  620. )
  621. .filter(
  622. integer2=Case(
  623. When(integer=2, then="min"),
  624. When(integer=3, then="max"),
  625. ),
  626. )
  627. .order_by("pk"),
  628. [(3, 4, 3, 4), (2, 2, 2, 3), (3, 4, 3, 4)],
  629. transform=itemgetter("integer", "integer2", "min", "max"),
  630. )
  631. def test_filter_with_aggregation_in_condition(self):
  632. self.assertQuerysetEqual(
  633. CaseTestModel.objects.values(*self.group_by_fields)
  634. .annotate(
  635. min=Min("fk_rel__integer"),
  636. max=Max("fk_rel__integer"),
  637. )
  638. .filter(
  639. integer=Case(
  640. When(integer2=F("min"), then=2),
  641. When(integer2=F("max"), then=3),
  642. ),
  643. )
  644. .order_by("pk"),
  645. [(3, 4, 3, 4), (2, 2, 2, 3), (3, 4, 3, 4)],
  646. transform=itemgetter("integer", "integer2", "min", "max"),
  647. )
  648. def test_filter_with_aggregation_in_predicate(self):
  649. self.assertQuerysetEqual(
  650. CaseTestModel.objects.values(*self.group_by_fields)
  651. .annotate(
  652. max=Max("fk_rel__integer"),
  653. )
  654. .filter(
  655. integer=Case(
  656. When(max=3, then=2),
  657. When(max=4, then=3),
  658. ),
  659. )
  660. .order_by("pk"),
  661. [(2, 3, 3), (3, 4, 4), (2, 2, 3), (3, 4, 4), (3, 3, 4)],
  662. transform=itemgetter("integer", "integer2", "max"),
  663. )
  664. def test_update(self):
  665. CaseTestModel.objects.update(
  666. string=Case(
  667. When(integer=1, then=Value("one")),
  668. When(integer=2, then=Value("two")),
  669. default=Value("other"),
  670. ),
  671. )
  672. self.assertQuerysetEqual(
  673. CaseTestModel.objects.order_by("pk"),
  674. [
  675. (1, "one"),
  676. (2, "two"),
  677. (3, "other"),
  678. (2, "two"),
  679. (3, "other"),
  680. (3, "other"),
  681. (4, "other"),
  682. ],
  683. transform=attrgetter("integer", "string"),
  684. )
  685. def test_update_without_default(self):
  686. CaseTestModel.objects.update(
  687. integer2=Case(
  688. When(integer=1, then=1),
  689. When(integer=2, then=2),
  690. ),
  691. )
  692. self.assertQuerysetEqual(
  693. CaseTestModel.objects.order_by("pk"),
  694. [(1, 1), (2, 2), (3, None), (2, 2), (3, None), (3, None), (4, None)],
  695. transform=attrgetter("integer", "integer2"),
  696. )
  697. def test_update_with_expression_as_value(self):
  698. CaseTestModel.objects.update(
  699. integer=Case(
  700. When(integer=1, then=F("integer") + 1),
  701. When(integer=2, then=F("integer") + 3),
  702. default="integer",
  703. ),
  704. )
  705. self.assertQuerysetEqual(
  706. CaseTestModel.objects.order_by("pk"),
  707. [("1", 2), ("2", 5), ("3", 3), ("2", 5), ("3", 3), ("3", 3), ("4", 4)],
  708. transform=attrgetter("string", "integer"),
  709. )
  710. def test_update_with_expression_as_condition(self):
  711. CaseTestModel.objects.update(
  712. string=Case(
  713. When(integer2=F("integer"), then=Value("equal")),
  714. When(integer2=F("integer") + 1, then=Value("+1")),
  715. ),
  716. )
  717. self.assertQuerysetEqual(
  718. CaseTestModel.objects.order_by("pk"),
  719. [
  720. (1, "equal"),
  721. (2, "+1"),
  722. (3, "+1"),
  723. (2, "equal"),
  724. (3, "+1"),
  725. (3, "equal"),
  726. (4, "+1"),
  727. ],
  728. transform=attrgetter("integer", "string"),
  729. )
  730. def test_update_with_join_in_condition_raise_field_error(self):
  731. with self.assertRaisesMessage(
  732. FieldError, "Joined field references are not permitted in this query"
  733. ):
  734. CaseTestModel.objects.update(
  735. integer=Case(
  736. When(integer2=F("o2o_rel__integer") + 1, then=2),
  737. When(integer2=F("o2o_rel__integer"), then=3),
  738. ),
  739. )
  740. def test_update_with_join_in_predicate_raise_field_error(self):
  741. with self.assertRaisesMessage(
  742. FieldError, "Joined field references are not permitted in this query"
  743. ):
  744. CaseTestModel.objects.update(
  745. string=Case(
  746. When(o2o_rel__integer=1, then=Value("one")),
  747. When(o2o_rel__integer=2, then=Value("two")),
  748. When(o2o_rel__integer=3, then=Value("three")),
  749. default=Value("other"),
  750. ),
  751. )
  752. def test_update_big_integer(self):
  753. CaseTestModel.objects.update(
  754. big_integer=Case(
  755. When(integer=1, then=1),
  756. When(integer=2, then=2),
  757. ),
  758. )
  759. self.assertQuerysetEqual(
  760. CaseTestModel.objects.order_by("pk"),
  761. [(1, 1), (2, 2), (3, None), (2, 2), (3, None), (3, None), (4, None)],
  762. transform=attrgetter("integer", "big_integer"),
  763. )
  764. def test_update_binary(self):
  765. CaseTestModel.objects.update(
  766. binary=Case(
  767. When(integer=1, then=b"one"),
  768. When(integer=2, then=b"two"),
  769. default=b"",
  770. ),
  771. )
  772. self.assertQuerysetEqual(
  773. CaseTestModel.objects.order_by("pk"),
  774. [
  775. (1, b"one"),
  776. (2, b"two"),
  777. (3, b""),
  778. (2, b"two"),
  779. (3, b""),
  780. (3, b""),
  781. (4, b""),
  782. ],
  783. transform=lambda o: (o.integer, bytes(o.binary)),
  784. )
  785. def test_update_boolean(self):
  786. CaseTestModel.objects.update(
  787. boolean=Case(
  788. When(integer=1, then=True),
  789. When(integer=2, then=True),
  790. default=False,
  791. ),
  792. )
  793. self.assertQuerysetEqual(
  794. CaseTestModel.objects.order_by("pk"),
  795. [
  796. (1, True),
  797. (2, True),
  798. (3, False),
  799. (2, True),
  800. (3, False),
  801. (3, False),
  802. (4, False),
  803. ],
  804. transform=attrgetter("integer", "boolean"),
  805. )
  806. def test_update_date(self):
  807. CaseTestModel.objects.update(
  808. date=Case(
  809. When(integer=1, then=date(2015, 1, 1)),
  810. When(integer=2, then=date(2015, 1, 2)),
  811. ),
  812. )
  813. self.assertQuerysetEqual(
  814. CaseTestModel.objects.order_by("pk"),
  815. [
  816. (1, date(2015, 1, 1)),
  817. (2, date(2015, 1, 2)),
  818. (3, None),
  819. (2, date(2015, 1, 2)),
  820. (3, None),
  821. (3, None),
  822. (4, None),
  823. ],
  824. transform=attrgetter("integer", "date"),
  825. )
  826. def test_update_date_time(self):
  827. CaseTestModel.objects.update(
  828. date_time=Case(
  829. When(integer=1, then=datetime(2015, 1, 1)),
  830. When(integer=2, then=datetime(2015, 1, 2)),
  831. ),
  832. )
  833. self.assertQuerysetEqual(
  834. CaseTestModel.objects.order_by("pk"),
  835. [
  836. (1, datetime(2015, 1, 1)),
  837. (2, datetime(2015, 1, 2)),
  838. (3, None),
  839. (2, datetime(2015, 1, 2)),
  840. (3, None),
  841. (3, None),
  842. (4, None),
  843. ],
  844. transform=attrgetter("integer", "date_time"),
  845. )
  846. def test_update_decimal(self):
  847. CaseTestModel.objects.update(
  848. decimal=Case(
  849. When(integer=1, then=Decimal("1.1")),
  850. When(
  851. integer=2, then=Value(Decimal("2.2"), output_field=DecimalField())
  852. ),
  853. ),
  854. )
  855. self.assertQuerysetEqual(
  856. CaseTestModel.objects.order_by("pk"),
  857. [
  858. (1, Decimal("1.1")),
  859. (2, Decimal("2.2")),
  860. (3, None),
  861. (2, Decimal("2.2")),
  862. (3, None),
  863. (3, None),
  864. (4, None),
  865. ],
  866. transform=attrgetter("integer", "decimal"),
  867. )
  868. def test_update_duration(self):
  869. CaseTestModel.objects.update(
  870. duration=Case(
  871. When(integer=1, then=timedelta(1)),
  872. When(integer=2, then=timedelta(2)),
  873. ),
  874. )
  875. self.assertQuerysetEqual(
  876. CaseTestModel.objects.order_by("pk"),
  877. [
  878. (1, timedelta(1)),
  879. (2, timedelta(2)),
  880. (3, None),
  881. (2, timedelta(2)),
  882. (3, None),
  883. (3, None),
  884. (4, None),
  885. ],
  886. transform=attrgetter("integer", "duration"),
  887. )
  888. def test_update_email(self):
  889. CaseTestModel.objects.update(
  890. email=Case(
  891. When(integer=1, then=Value("1@example.com")),
  892. When(integer=2, then=Value("2@example.com")),
  893. default=Value(""),
  894. ),
  895. )
  896. self.assertQuerysetEqual(
  897. CaseTestModel.objects.order_by("pk"),
  898. [
  899. (1, "1@example.com"),
  900. (2, "2@example.com"),
  901. (3, ""),
  902. (2, "2@example.com"),
  903. (3, ""),
  904. (3, ""),
  905. (4, ""),
  906. ],
  907. transform=attrgetter("integer", "email"),
  908. )
  909. def test_update_file(self):
  910. CaseTestModel.objects.update(
  911. file=Case(
  912. When(integer=1, then=Value("~/1")),
  913. When(integer=2, then=Value("~/2")),
  914. ),
  915. )
  916. self.assertQuerysetEqual(
  917. CaseTestModel.objects.order_by("pk"),
  918. [(1, "~/1"), (2, "~/2"), (3, ""), (2, "~/2"), (3, ""), (3, ""), (4, "")],
  919. transform=lambda o: (o.integer, str(o.file)),
  920. )
  921. def test_update_file_path(self):
  922. CaseTestModel.objects.update(
  923. file_path=Case(
  924. When(integer=1, then=Value("~/1")),
  925. When(integer=2, then=Value("~/2")),
  926. default=Value(""),
  927. ),
  928. )
  929. self.assertQuerysetEqual(
  930. CaseTestModel.objects.order_by("pk"),
  931. [(1, "~/1"), (2, "~/2"), (3, ""), (2, "~/2"), (3, ""), (3, ""), (4, "")],
  932. transform=attrgetter("integer", "file_path"),
  933. )
  934. def test_update_float(self):
  935. CaseTestModel.objects.update(
  936. float=Case(
  937. When(integer=1, then=1.1),
  938. When(integer=2, then=2.2),
  939. ),
  940. )
  941. self.assertQuerysetEqual(
  942. CaseTestModel.objects.order_by("pk"),
  943. [(1, 1.1), (2, 2.2), (3, None), (2, 2.2), (3, None), (3, None), (4, None)],
  944. transform=attrgetter("integer", "float"),
  945. )
  946. @unittest.skipUnless(Image, "Pillow not installed")
  947. def test_update_image(self):
  948. CaseTestModel.objects.update(
  949. image=Case(
  950. When(integer=1, then=Value("~/1")),
  951. When(integer=2, then=Value("~/2")),
  952. ),
  953. )
  954. self.assertQuerysetEqual(
  955. CaseTestModel.objects.order_by("pk"),
  956. [(1, "~/1"), (2, "~/2"), (3, ""), (2, "~/2"), (3, ""), (3, ""), (4, "")],
  957. transform=lambda o: (o.integer, str(o.image)),
  958. )
  959. def test_update_generic_ip_address(self):
  960. CaseTestModel.objects.update(
  961. generic_ip_address=Case(
  962. When(integer=1, then=Value("1.1.1.1")),
  963. When(integer=2, then=Value("2.2.2.2")),
  964. output_field=GenericIPAddressField(),
  965. ),
  966. )
  967. self.assertQuerysetEqual(
  968. CaseTestModel.objects.order_by("pk"),
  969. [
  970. (1, "1.1.1.1"),
  971. (2, "2.2.2.2"),
  972. (3, None),
  973. (2, "2.2.2.2"),
  974. (3, None),
  975. (3, None),
  976. (4, None),
  977. ],
  978. transform=attrgetter("integer", "generic_ip_address"),
  979. )
  980. def test_update_null_boolean(self):
  981. CaseTestModel.objects.update(
  982. null_boolean=Case(
  983. When(integer=1, then=True),
  984. When(integer=2, then=False),
  985. ),
  986. )
  987. self.assertQuerysetEqual(
  988. CaseTestModel.objects.order_by("pk"),
  989. [
  990. (1, True),
  991. (2, False),
  992. (3, None),
  993. (2, False),
  994. (3, None),
  995. (3, None),
  996. (4, None),
  997. ],
  998. transform=attrgetter("integer", "null_boolean"),
  999. )
  1000. def test_update_positive_big_integer(self):
  1001. CaseTestModel.objects.update(
  1002. positive_big_integer=Case(
  1003. When(integer=1, then=1),
  1004. When(integer=2, then=2),
  1005. ),
  1006. )
  1007. self.assertQuerysetEqual(
  1008. CaseTestModel.objects.order_by("pk"),
  1009. [(1, 1), (2, 2), (3, None), (2, 2), (3, None), (3, None), (4, None)],
  1010. transform=attrgetter("integer", "positive_big_integer"),
  1011. )
  1012. def test_update_positive_integer(self):
  1013. CaseTestModel.objects.update(
  1014. positive_integer=Case(
  1015. When(integer=1, then=1),
  1016. When(integer=2, then=2),
  1017. ),
  1018. )
  1019. self.assertQuerysetEqual(
  1020. CaseTestModel.objects.order_by("pk"),
  1021. [(1, 1), (2, 2), (3, None), (2, 2), (3, None), (3, None), (4, None)],
  1022. transform=attrgetter("integer", "positive_integer"),
  1023. )
  1024. def test_update_positive_small_integer(self):
  1025. CaseTestModel.objects.update(
  1026. positive_small_integer=Case(
  1027. When(integer=1, then=1),
  1028. When(integer=2, then=2),
  1029. ),
  1030. )
  1031. self.assertQuerysetEqual(
  1032. CaseTestModel.objects.order_by("pk"),
  1033. [(1, 1), (2, 2), (3, None), (2, 2), (3, None), (3, None), (4, None)],
  1034. transform=attrgetter("integer", "positive_small_integer"),
  1035. )
  1036. def test_update_slug(self):
  1037. CaseTestModel.objects.update(
  1038. slug=Case(
  1039. When(integer=1, then=Value("1")),
  1040. When(integer=2, then=Value("2")),
  1041. default=Value(""),
  1042. ),
  1043. )
  1044. self.assertQuerysetEqual(
  1045. CaseTestModel.objects.order_by("pk"),
  1046. [(1, "1"), (2, "2"), (3, ""), (2, "2"), (3, ""), (3, ""), (4, "")],
  1047. transform=attrgetter("integer", "slug"),
  1048. )
  1049. def test_update_small_integer(self):
  1050. CaseTestModel.objects.update(
  1051. small_integer=Case(
  1052. When(integer=1, then=1),
  1053. When(integer=2, then=2),
  1054. ),
  1055. )
  1056. self.assertQuerysetEqual(
  1057. CaseTestModel.objects.order_by("pk"),
  1058. [(1, 1), (2, 2), (3, None), (2, 2), (3, None), (3, None), (4, None)],
  1059. transform=attrgetter("integer", "small_integer"),
  1060. )
  1061. def test_update_string(self):
  1062. CaseTestModel.objects.filter(string__in=["1", "2"]).update(
  1063. string=Case(
  1064. When(integer=1, then=Value("1")),
  1065. When(integer=2, then=Value("2")),
  1066. ),
  1067. )
  1068. self.assertQuerysetEqual(
  1069. CaseTestModel.objects.filter(string__in=["1", "2"]).order_by("pk"),
  1070. [(1, "1"), (2, "2"), (2, "2")],
  1071. transform=attrgetter("integer", "string"),
  1072. )
  1073. def test_update_text(self):
  1074. CaseTestModel.objects.update(
  1075. text=Case(
  1076. When(integer=1, then=Value("1")),
  1077. When(integer=2, then=Value("2")),
  1078. default=Value(""),
  1079. ),
  1080. )
  1081. self.assertQuerysetEqual(
  1082. CaseTestModel.objects.order_by("pk"),
  1083. [(1, "1"), (2, "2"), (3, ""), (2, "2"), (3, ""), (3, ""), (4, "")],
  1084. transform=attrgetter("integer", "text"),
  1085. )
  1086. def test_update_time(self):
  1087. CaseTestModel.objects.update(
  1088. time=Case(
  1089. When(integer=1, then=time(1)),
  1090. When(integer=2, then=time(2)),
  1091. ),
  1092. )
  1093. self.assertQuerysetEqual(
  1094. CaseTestModel.objects.order_by("pk"),
  1095. [
  1096. (1, time(1)),
  1097. (2, time(2)),
  1098. (3, None),
  1099. (2, time(2)),
  1100. (3, None),
  1101. (3, None),
  1102. (4, None),
  1103. ],
  1104. transform=attrgetter("integer", "time"),
  1105. )
  1106. def test_update_url(self):
  1107. CaseTestModel.objects.update(
  1108. url=Case(
  1109. When(integer=1, then=Value("http://1.example.com/")),
  1110. When(integer=2, then=Value("http://2.example.com/")),
  1111. default=Value(""),
  1112. ),
  1113. )
  1114. self.assertQuerysetEqual(
  1115. CaseTestModel.objects.order_by("pk"),
  1116. [
  1117. (1, "http://1.example.com/"),
  1118. (2, "http://2.example.com/"),
  1119. (3, ""),
  1120. (2, "http://2.example.com/"),
  1121. (3, ""),
  1122. (3, ""),
  1123. (4, ""),
  1124. ],
  1125. transform=attrgetter("integer", "url"),
  1126. )
  1127. def test_update_uuid(self):
  1128. CaseTestModel.objects.update(
  1129. uuid=Case(
  1130. When(integer=1, then=UUID("11111111111111111111111111111111")),
  1131. When(integer=2, then=UUID("22222222222222222222222222222222")),
  1132. ),
  1133. )
  1134. self.assertQuerysetEqual(
  1135. CaseTestModel.objects.order_by("pk"),
  1136. [
  1137. (1, UUID("11111111111111111111111111111111")),
  1138. (2, UUID("22222222222222222222222222222222")),
  1139. (3, None),
  1140. (2, UUID("22222222222222222222222222222222")),
  1141. (3, None),
  1142. (3, None),
  1143. (4, None),
  1144. ],
  1145. transform=attrgetter("integer", "uuid"),
  1146. )
  1147. def test_update_fk(self):
  1148. obj1, obj2 = CaseTestModel.objects.all()[:2]
  1149. CaseTestModel.objects.update(
  1150. fk=Case(
  1151. When(integer=1, then=obj1.pk),
  1152. When(integer=2, then=obj2.pk),
  1153. ),
  1154. )
  1155. self.assertQuerysetEqual(
  1156. CaseTestModel.objects.order_by("pk"),
  1157. [
  1158. (1, obj1.pk),
  1159. (2, obj2.pk),
  1160. (3, None),
  1161. (2, obj2.pk),
  1162. (3, None),
  1163. (3, None),
  1164. (4, None),
  1165. ],
  1166. transform=attrgetter("integer", "fk_id"),
  1167. )
  1168. def test_lookup_in_condition(self):
  1169. self.assertQuerysetEqual(
  1170. CaseTestModel.objects.annotate(
  1171. test=Case(
  1172. When(integer__lt=2, then=Value("less than 2")),
  1173. When(integer__gt=2, then=Value("greater than 2")),
  1174. default=Value("equal to 2"),
  1175. ),
  1176. ).order_by("pk"),
  1177. [
  1178. (1, "less than 2"),
  1179. (2, "equal to 2"),
  1180. (3, "greater than 2"),
  1181. (2, "equal to 2"),
  1182. (3, "greater than 2"),
  1183. (3, "greater than 2"),
  1184. (4, "greater than 2"),
  1185. ],
  1186. transform=attrgetter("integer", "test"),
  1187. )
  1188. def test_lookup_different_fields(self):
  1189. self.assertQuerysetEqual(
  1190. CaseTestModel.objects.annotate(
  1191. test=Case(
  1192. When(integer=2, integer2=3, then=Value("when")),
  1193. default=Value("default"),
  1194. ),
  1195. ).order_by("pk"),
  1196. [
  1197. (1, 1, "default"),
  1198. (2, 3, "when"),
  1199. (3, 4, "default"),
  1200. (2, 2, "default"),
  1201. (3, 4, "default"),
  1202. (3, 3, "default"),
  1203. (4, 5, "default"),
  1204. ],
  1205. transform=attrgetter("integer", "integer2", "test"),
  1206. )
  1207. def test_combined_q_object(self):
  1208. self.assertQuerysetEqual(
  1209. CaseTestModel.objects.annotate(
  1210. test=Case(
  1211. When(Q(integer=2) | Q(integer2=3), then=Value("when")),
  1212. default=Value("default"),
  1213. ),
  1214. ).order_by("pk"),
  1215. [
  1216. (1, 1, "default"),
  1217. (2, 3, "when"),
  1218. (3, 4, "default"),
  1219. (2, 2, "when"),
  1220. (3, 4, "default"),
  1221. (3, 3, "when"),
  1222. (4, 5, "default"),
  1223. ],
  1224. transform=attrgetter("integer", "integer2", "test"),
  1225. )
  1226. def test_order_by_conditional_implicit(self):
  1227. self.assertQuerysetEqual(
  1228. CaseTestModel.objects.filter(integer__lte=2)
  1229. .annotate(
  1230. test=Case(
  1231. When(integer=1, then=2),
  1232. When(integer=2, then=1),
  1233. default=3,
  1234. )
  1235. )
  1236. .order_by("test", "pk"),
  1237. [(2, 1), (2, 1), (1, 2)],
  1238. transform=attrgetter("integer", "test"),
  1239. )
  1240. def test_order_by_conditional_explicit(self):
  1241. self.assertQuerysetEqual(
  1242. CaseTestModel.objects.filter(integer__lte=2)
  1243. .annotate(
  1244. test=Case(
  1245. When(integer=1, then=2),
  1246. When(integer=2, then=1),
  1247. default=3,
  1248. )
  1249. )
  1250. .order_by(F("test").asc(), "pk"),
  1251. [(2, 1), (2, 1), (1, 2)],
  1252. transform=attrgetter("integer", "test"),
  1253. )
  1254. def test_join_promotion(self):
  1255. o = CaseTestModel.objects.create(integer=1, integer2=1, string="1")
  1256. # Testing that:
  1257. # 1. There isn't any object on the remote side of the fk_rel
  1258. # relation. If the query used inner joins, then the join to fk_rel
  1259. # would remove o from the results. So, in effect we are testing that
  1260. # we are promoting the fk_rel join to a left outer join here.
  1261. # 2. The default value of 3 is generated for the case expression.
  1262. self.assertQuerysetEqual(
  1263. CaseTestModel.objects.filter(pk=o.pk).annotate(
  1264. foo=Case(
  1265. When(fk_rel__pk=1, then=2),
  1266. default=3,
  1267. ),
  1268. ),
  1269. [(o, 3)],
  1270. lambda x: (x, x.foo),
  1271. )
  1272. # Now 2 should be generated, as the fk_rel is null.
  1273. self.assertQuerysetEqual(
  1274. CaseTestModel.objects.filter(pk=o.pk).annotate(
  1275. foo=Case(
  1276. When(fk_rel__isnull=True, then=2),
  1277. default=3,
  1278. ),
  1279. ),
  1280. [(o, 2)],
  1281. lambda x: (x, x.foo),
  1282. )
  1283. def test_join_promotion_multiple_annotations(self):
  1284. o = CaseTestModel.objects.create(integer=1, integer2=1, string="1")
  1285. # Testing that:
  1286. # 1. There isn't any object on the remote side of the fk_rel
  1287. # relation. If the query used inner joins, then the join to fk_rel
  1288. # would remove o from the results. So, in effect we are testing that
  1289. # we are promoting the fk_rel join to a left outer join here.
  1290. # 2. The default value of 3 is generated for the case expression.
  1291. self.assertQuerysetEqual(
  1292. CaseTestModel.objects.filter(pk=o.pk).annotate(
  1293. foo=Case(
  1294. When(fk_rel__pk=1, then=2),
  1295. default=3,
  1296. ),
  1297. bar=Case(
  1298. When(fk_rel__pk=1, then=4),
  1299. default=5,
  1300. ),
  1301. ),
  1302. [(o, 3, 5)],
  1303. lambda x: (x, x.foo, x.bar),
  1304. )
  1305. # Now 2 should be generated, as the fk_rel is null.
  1306. self.assertQuerysetEqual(
  1307. CaseTestModel.objects.filter(pk=o.pk).annotate(
  1308. foo=Case(
  1309. When(fk_rel__isnull=True, then=2),
  1310. default=3,
  1311. ),
  1312. bar=Case(
  1313. When(fk_rel__isnull=True, then=4),
  1314. default=5,
  1315. ),
  1316. ),
  1317. [(o, 2, 4)],
  1318. lambda x: (x, x.foo, x.bar),
  1319. )
  1320. def test_m2m_exclude(self):
  1321. CaseTestModel.objects.create(integer=10, integer2=1, string="1")
  1322. qs = (
  1323. CaseTestModel.objects.values_list("id", "integer")
  1324. .annotate(
  1325. cnt=Sum(
  1326. Case(When(~Q(fk_rel__integer=1), then=1), default=2),
  1327. ),
  1328. )
  1329. .order_by("integer")
  1330. )
  1331. # The first o has 2 as its fk_rel__integer=1, thus it hits the
  1332. # default=2 case. The other ones have 2 as the result as they have 2
  1333. # fk_rel objects, except for integer=4 and integer=10 (created above).
  1334. # The integer=4 case has one integer, thus the result is 1, and
  1335. # integer=10 doesn't have any and this too generates 1 (instead of 0)
  1336. # as ~Q() also matches nulls.
  1337. self.assertQuerysetEqual(
  1338. qs,
  1339. [(1, 2), (2, 2), (2, 2), (3, 2), (3, 2), (3, 2), (4, 1), (10, 1)],
  1340. lambda x: x[1:],
  1341. )
  1342. def test_m2m_reuse(self):
  1343. CaseTestModel.objects.create(integer=10, integer2=1, string="1")
  1344. # Need to use values before annotate so that Oracle will not group
  1345. # by fields it isn't capable of grouping by.
  1346. qs = (
  1347. CaseTestModel.objects.values_list("id", "integer")
  1348. .annotate(
  1349. cnt=Sum(
  1350. Case(When(~Q(fk_rel__integer=1), then=1), default=2),
  1351. ),
  1352. )
  1353. .annotate(
  1354. cnt2=Sum(
  1355. Case(When(~Q(fk_rel__integer=1), then=1), default=2),
  1356. ),
  1357. )
  1358. .order_by("integer")
  1359. )
  1360. self.assertEqual(str(qs.query).count(" JOIN "), 1)
  1361. self.assertQuerysetEqual(
  1362. qs,
  1363. [
  1364. (1, 2, 2),
  1365. (2, 2, 2),
  1366. (2, 2, 2),
  1367. (3, 2, 2),
  1368. (3, 2, 2),
  1369. (3, 2, 2),
  1370. (4, 1, 1),
  1371. (10, 1, 1),
  1372. ],
  1373. lambda x: x[1:],
  1374. )
  1375. def test_aggregation_empty_cases(self):
  1376. tests = [
  1377. # Empty cases and default.
  1378. (Case(output_field=IntegerField()), None),
  1379. # Empty cases and a constant default.
  1380. (Case(default=Value("empty")), "empty"),
  1381. # Empty cases and column in the default.
  1382. (Case(default=F("url")), ""),
  1383. ]
  1384. for case, value in tests:
  1385. with self.subTest(case=case):
  1386. self.assertQuerysetEqual(
  1387. CaseTestModel.objects.values("string")
  1388. .annotate(
  1389. case=case,
  1390. integer_sum=Sum("integer"),
  1391. )
  1392. .order_by("string"),
  1393. [
  1394. ("1", value, 1),
  1395. ("2", value, 4),
  1396. ("3", value, 9),
  1397. ("4", value, 4),
  1398. ],
  1399. transform=itemgetter("string", "case", "integer_sum"),
  1400. )
  1401. class CaseDocumentationExamples(TestCase):
  1402. @classmethod
  1403. def setUpTestData(cls):
  1404. Client.objects.create(
  1405. name="Jane Doe",
  1406. account_type=Client.REGULAR,
  1407. registered_on=date.today() - timedelta(days=36),
  1408. )
  1409. Client.objects.create(
  1410. name="James Smith",
  1411. account_type=Client.GOLD,
  1412. registered_on=date.today() - timedelta(days=5),
  1413. )
  1414. Client.objects.create(
  1415. name="Jack Black",
  1416. account_type=Client.PLATINUM,
  1417. registered_on=date.today() - timedelta(days=10 * 365),
  1418. )
  1419. def test_simple_example(self):
  1420. self.assertQuerysetEqual(
  1421. Client.objects.annotate(
  1422. discount=Case(
  1423. When(account_type=Client.GOLD, then=Value("5%")),
  1424. When(account_type=Client.PLATINUM, then=Value("10%")),
  1425. default=Value("0%"),
  1426. ),
  1427. ).order_by("pk"),
  1428. [("Jane Doe", "0%"), ("James Smith", "5%"), ("Jack Black", "10%")],
  1429. transform=attrgetter("name", "discount"),
  1430. )
  1431. def test_lookup_example(self):
  1432. a_month_ago = date.today() - timedelta(days=30)
  1433. a_year_ago = date.today() - timedelta(days=365)
  1434. self.assertQuerysetEqual(
  1435. Client.objects.annotate(
  1436. discount=Case(
  1437. When(registered_on__lte=a_year_ago, then=Value("10%")),
  1438. When(registered_on__lte=a_month_ago, then=Value("5%")),
  1439. default=Value("0%"),
  1440. ),
  1441. ).order_by("pk"),
  1442. [("Jane Doe", "5%"), ("James Smith", "0%"), ("Jack Black", "10%")],
  1443. transform=attrgetter("name", "discount"),
  1444. )
  1445. def test_conditional_update_example(self):
  1446. a_month_ago = date.today() - timedelta(days=30)
  1447. a_year_ago = date.today() - timedelta(days=365)
  1448. Client.objects.update(
  1449. account_type=Case(
  1450. When(registered_on__lte=a_year_ago, then=Value(Client.PLATINUM)),
  1451. When(registered_on__lte=a_month_ago, then=Value(Client.GOLD)),
  1452. default=Value(Client.REGULAR),
  1453. ),
  1454. )
  1455. self.assertQuerysetEqual(
  1456. Client.objects.order_by("pk"),
  1457. [("Jane Doe", "G"), ("James Smith", "R"), ("Jack Black", "P")],
  1458. transform=attrgetter("name", "account_type"),
  1459. )
  1460. def test_conditional_aggregation_example(self):
  1461. Client.objects.create(
  1462. name="Jean Grey",
  1463. account_type=Client.REGULAR,
  1464. registered_on=date.today(),
  1465. )
  1466. Client.objects.create(
  1467. name="James Bond",
  1468. account_type=Client.PLATINUM,
  1469. registered_on=date.today(),
  1470. )
  1471. Client.objects.create(
  1472. name="Jane Porter",
  1473. account_type=Client.PLATINUM,
  1474. registered_on=date.today(),
  1475. )
  1476. self.assertEqual(
  1477. Client.objects.aggregate(
  1478. regular=Count("pk", filter=Q(account_type=Client.REGULAR)),
  1479. gold=Count("pk", filter=Q(account_type=Client.GOLD)),
  1480. platinum=Count("pk", filter=Q(account_type=Client.PLATINUM)),
  1481. ),
  1482. {"regular": 2, "gold": 1, "platinum": 3},
  1483. )
  1484. # This was the example before the filter argument was added.
  1485. self.assertEqual(
  1486. Client.objects.aggregate(
  1487. regular=Sum(
  1488. Case(
  1489. When(account_type=Client.REGULAR, then=1),
  1490. )
  1491. ),
  1492. gold=Sum(
  1493. Case(
  1494. When(account_type=Client.GOLD, then=1),
  1495. )
  1496. ),
  1497. platinum=Sum(
  1498. Case(
  1499. When(account_type=Client.PLATINUM, then=1),
  1500. )
  1501. ),
  1502. ),
  1503. {"regular": 2, "gold": 1, "platinum": 3},
  1504. )
  1505. def test_filter_example(self):
  1506. a_month_ago = date.today() - timedelta(days=30)
  1507. a_year_ago = date.today() - timedelta(days=365)
  1508. self.assertQuerysetEqual(
  1509. Client.objects.filter(
  1510. registered_on__lte=Case(
  1511. When(account_type=Client.GOLD, then=a_month_ago),
  1512. When(account_type=Client.PLATINUM, then=a_year_ago),
  1513. ),
  1514. ),
  1515. [("Jack Black", "P")],
  1516. transform=attrgetter("name", "account_type"),
  1517. )
  1518. def test_hash(self):
  1519. expression_1 = Case(
  1520. When(account_type__in=[Client.REGULAR, Client.GOLD], then=1),
  1521. default=2,
  1522. output_field=IntegerField(),
  1523. )
  1524. expression_2 = Case(
  1525. When(account_type__in=(Client.REGULAR, Client.GOLD), then=1),
  1526. default=2,
  1527. output_field=IntegerField(),
  1528. )
  1529. expression_3 = Case(
  1530. When(account_type__in=[Client.REGULAR, Client.GOLD], then=1), default=2
  1531. )
  1532. expression_4 = Case(
  1533. When(account_type__in=[Client.PLATINUM, Client.GOLD], then=2), default=1
  1534. )
  1535. self.assertEqual(hash(expression_1), hash(expression_2))
  1536. self.assertNotEqual(hash(expression_2), hash(expression_3))
  1537. self.assertNotEqual(hash(expression_1), hash(expression_4))
  1538. self.assertNotEqual(hash(expression_3), hash(expression_4))
  1539. class CaseWhenTests(SimpleTestCase):
  1540. def test_only_when_arguments(self):
  1541. msg = "Positional arguments must all be When objects."
  1542. with self.assertRaisesMessage(TypeError, msg):
  1543. Case(When(Q(pk__in=[])), object())
  1544. def test_invalid_when_constructor_args(self):
  1545. msg = (
  1546. "When() supports a Q object, a boolean expression, or lookups as "
  1547. "a condition."
  1548. )
  1549. with self.assertRaisesMessage(TypeError, msg):
  1550. When(condition=object())
  1551. with self.assertRaisesMessage(TypeError, msg):
  1552. When(condition=Value(1))
  1553. with self.assertRaisesMessage(TypeError, msg):
  1554. When(Value(1), string="1")
  1555. with self.assertRaisesMessage(TypeError, msg):
  1556. When()
  1557. def test_empty_q_object(self):
  1558. msg = "An empty Q() can't be used as a When() condition."
  1559. with self.assertRaisesMessage(ValueError, msg):
  1560. When(Q(), then=Value(True))