tests.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. from datetime import date, datetime, timedelta
  2. from operator import attrgetter
  3. from django.db import IntegrityError
  4. from django.test import TestCase
  5. from .models import (
  6. CustomMembership, Employee, Event, Friendship, Group, Ingredient,
  7. Invitation, Membership, Person, PersonSelfRefM2M, Recipe, RecipeIngredient,
  8. Relationship, SymmetricalFriendship,
  9. )
  10. class M2mThroughTests(TestCase):
  11. @classmethod
  12. def setUpTestData(cls):
  13. cls.bob = Person.objects.create(name='Bob')
  14. cls.jim = Person.objects.create(name='Jim')
  15. cls.jane = Person.objects.create(name='Jane')
  16. cls.rock = Group.objects.create(name='Rock')
  17. cls.roll = Group.objects.create(name='Roll')
  18. def test_retrieve_intermediate_items(self):
  19. Membership.objects.create(person=self.jim, group=self.rock)
  20. Membership.objects.create(person=self.jane, group=self.rock)
  21. expected = ['Jane', 'Jim']
  22. self.assertQuerysetEqual(
  23. self.rock.members.all(),
  24. expected,
  25. attrgetter("name")
  26. )
  27. def test_get_on_intermediate_model(self):
  28. Membership.objects.create(person=self.jane, group=self.rock)
  29. queryset = Membership.objects.get(person=self.jane, group=self.rock)
  30. self.assertEqual(
  31. repr(queryset),
  32. '<Membership: Jane is a member of Rock>'
  33. )
  34. def test_filter_on_intermediate_model(self):
  35. m1 = Membership.objects.create(person=self.jim, group=self.rock)
  36. m2 = Membership.objects.create(person=self.jane, group=self.rock)
  37. queryset = Membership.objects.filter(group=self.rock)
  38. self.assertSequenceEqual(queryset, [m1, m2])
  39. def test_add_on_m2m_with_intermediate_model(self):
  40. self.rock.members.add(self.bob, through_defaults={'invite_reason': 'He is good.'})
  41. self.assertSequenceEqual(self.rock.members.all(), [self.bob])
  42. self.assertEqual(self.rock.membership_set.get().invite_reason, 'He is good.')
  43. def test_add_on_m2m_with_intermediate_model_callable_through_default(self):
  44. def invite_reason_callable():
  45. return 'They were good at %s' % datetime.now()
  46. self.rock.members.add(
  47. self.bob, self.jane,
  48. through_defaults={'invite_reason': invite_reason_callable},
  49. )
  50. self.assertSequenceEqual(self.rock.members.all(), [self.bob, self.jane])
  51. self.assertEqual(
  52. self.rock.membership_set.filter(
  53. invite_reason__startswith='They were good at ',
  54. ).count(),
  55. 2,
  56. )
  57. # invite_reason_callable() is called once.
  58. self.assertEqual(
  59. self.bob.membership_set.get().invite_reason,
  60. self.jane.membership_set.get().invite_reason,
  61. )
  62. def test_set_on_m2m_with_intermediate_model_callable_through_default(self):
  63. self.rock.members.set(
  64. [self.bob, self.jane],
  65. through_defaults={'invite_reason': lambda: 'Why not?'},
  66. )
  67. self.assertSequenceEqual(self.rock.members.all(), [self.bob, self.jane])
  68. self.assertEqual(
  69. self.rock.membership_set.filter(
  70. invite_reason__startswith='Why not?',
  71. ).count(),
  72. 2,
  73. )
  74. def test_add_on_m2m_with_intermediate_model_value_required(self):
  75. self.rock.nodefaultsnonulls.add(self.jim, through_defaults={'nodefaultnonull': 1})
  76. self.assertEqual(self.rock.testnodefaultsornulls_set.get().nodefaultnonull, 1)
  77. def test_add_on_m2m_with_intermediate_model_value_required_fails(self):
  78. with self.assertRaises(IntegrityError):
  79. self.rock.nodefaultsnonulls.add(self.jim)
  80. def test_create_on_m2m_with_intermediate_model(self):
  81. annie = self.rock.members.create(name='Annie', through_defaults={'invite_reason': 'She was just awesome.'})
  82. self.assertSequenceEqual(self.rock.members.all(), [annie])
  83. self.assertEqual(self.rock.membership_set.get().invite_reason, 'She was just awesome.')
  84. def test_create_on_m2m_with_intermediate_model_callable_through_default(self):
  85. annie = self.rock.members.create(
  86. name='Annie',
  87. through_defaults={'invite_reason': lambda: 'She was just awesome.'},
  88. )
  89. self.assertSequenceEqual(self.rock.members.all(), [annie])
  90. self.assertEqual(
  91. self.rock.membership_set.get().invite_reason,
  92. 'She was just awesome.',
  93. )
  94. def test_create_on_m2m_with_intermediate_model_value_required(self):
  95. self.rock.nodefaultsnonulls.create(name='Test', through_defaults={'nodefaultnonull': 1})
  96. self.assertEqual(self.rock.testnodefaultsornulls_set.get().nodefaultnonull, 1)
  97. def test_create_on_m2m_with_intermediate_model_value_required_fails(self):
  98. with self.assertRaises(IntegrityError):
  99. self.rock.nodefaultsnonulls.create(name='Test')
  100. def test_get_or_create_on_m2m_with_intermediate_model_value_required(self):
  101. self.rock.nodefaultsnonulls.get_or_create(name='Test', through_defaults={'nodefaultnonull': 1})
  102. self.assertEqual(self.rock.testnodefaultsornulls_set.get().nodefaultnonull, 1)
  103. def test_get_or_create_on_m2m_with_intermediate_model_value_required_fails(self):
  104. with self.assertRaises(IntegrityError):
  105. self.rock.nodefaultsnonulls.get_or_create(name='Test')
  106. def test_update_or_create_on_m2m_with_intermediate_model_value_required(self):
  107. self.rock.nodefaultsnonulls.update_or_create(name='Test', through_defaults={'nodefaultnonull': 1})
  108. self.assertEqual(self.rock.testnodefaultsornulls_set.get().nodefaultnonull, 1)
  109. def test_update_or_create_on_m2m_with_intermediate_model_value_required_fails(self):
  110. with self.assertRaises(IntegrityError):
  111. self.rock.nodefaultsnonulls.update_or_create(name='Test')
  112. def test_remove_on_m2m_with_intermediate_model(self):
  113. Membership.objects.create(person=self.jim, group=self.rock)
  114. self.rock.members.remove(self.jim)
  115. self.assertSequenceEqual(self.rock.members.all(), [])
  116. def test_remove_on_m2m_with_intermediate_model_multiple(self):
  117. Membership.objects.create(person=self.jim, group=self.rock, invite_reason='1')
  118. Membership.objects.create(person=self.jim, group=self.rock, invite_reason='2')
  119. self.assertSequenceEqual(self.rock.members.all(), [self.jim, self.jim])
  120. self.rock.members.remove(self.jim)
  121. self.assertSequenceEqual(self.rock.members.all(), [])
  122. def test_set_on_m2m_with_intermediate_model(self):
  123. members = list(Person.objects.filter(name__in=['Bob', 'Jim']))
  124. self.rock.members.set(members)
  125. self.assertSequenceEqual(self.rock.members.all(), [self.bob, self.jim])
  126. def test_set_on_m2m_with_intermediate_model_value_required(self):
  127. self.rock.nodefaultsnonulls.set([self.jim], through_defaults={'nodefaultnonull': 1})
  128. self.assertEqual(self.rock.testnodefaultsornulls_set.get().nodefaultnonull, 1)
  129. self.rock.nodefaultsnonulls.set([self.jim], through_defaults={'nodefaultnonull': 2})
  130. self.assertEqual(self.rock.testnodefaultsornulls_set.get().nodefaultnonull, 1)
  131. self.rock.nodefaultsnonulls.set([self.jim], through_defaults={'nodefaultnonull': 2}, clear=True)
  132. self.assertEqual(self.rock.testnodefaultsornulls_set.get().nodefaultnonull, 2)
  133. def test_set_on_m2m_with_intermediate_model_value_required_fails(self):
  134. with self.assertRaises(IntegrityError):
  135. self.rock.nodefaultsnonulls.set([self.jim])
  136. def test_clear_removes_all_the_m2m_relationships(self):
  137. Membership.objects.create(person=self.jim, group=self.rock)
  138. Membership.objects.create(person=self.jane, group=self.rock)
  139. self.rock.members.clear()
  140. self.assertQuerysetEqual(
  141. self.rock.members.all(),
  142. []
  143. )
  144. def test_retrieve_reverse_intermediate_items(self):
  145. Membership.objects.create(person=self.jim, group=self.rock)
  146. Membership.objects.create(person=self.jim, group=self.roll)
  147. expected = ['Rock', 'Roll']
  148. self.assertQuerysetEqual(
  149. self.jim.group_set.all(),
  150. expected,
  151. attrgetter("name")
  152. )
  153. def test_add_on_reverse_m2m_with_intermediate_model(self):
  154. self.bob.group_set.add(self.rock)
  155. self.assertSequenceEqual(self.bob.group_set.all(), [self.rock])
  156. def test_create_on_reverse_m2m_with_intermediate_model(self):
  157. funk = self.bob.group_set.create(name='Funk')
  158. self.assertSequenceEqual(self.bob.group_set.all(), [funk])
  159. def test_remove_on_reverse_m2m_with_intermediate_model(self):
  160. Membership.objects.create(person=self.bob, group=self.rock)
  161. self.bob.group_set.remove(self.rock)
  162. self.assertSequenceEqual(self.bob.group_set.all(), [])
  163. def test_set_on_reverse_m2m_with_intermediate_model(self):
  164. members = list(Group.objects.filter(name__in=['Rock', 'Roll']))
  165. self.bob.group_set.set(members)
  166. self.assertSequenceEqual(self.bob.group_set.all(), [self.rock, self.roll])
  167. def test_clear_on_reverse_removes_all_the_m2m_relationships(self):
  168. Membership.objects.create(person=self.jim, group=self.rock)
  169. Membership.objects.create(person=self.jim, group=self.roll)
  170. self.jim.group_set.clear()
  171. self.assertQuerysetEqual(
  172. self.jim.group_set.all(),
  173. []
  174. )
  175. def test_query_model_by_attribute_name_of_related_model(self):
  176. Membership.objects.create(person=self.jim, group=self.rock)
  177. Membership.objects.create(person=self.jane, group=self.rock)
  178. Membership.objects.create(person=self.bob, group=self.roll)
  179. Membership.objects.create(person=self.jim, group=self.roll)
  180. Membership.objects.create(person=self.jane, group=self.roll)
  181. self.assertQuerysetEqual(
  182. Group.objects.filter(members__name='Bob'),
  183. ['Roll'],
  184. attrgetter("name")
  185. )
  186. def test_order_by_relational_field_through_model(self):
  187. today = datetime.now()
  188. yesterday = today - timedelta(days=1)
  189. CustomMembership.objects.create(person=self.jim, group=self.rock, date_joined=yesterday)
  190. CustomMembership.objects.create(person=self.bob, group=self.rock, date_joined=today)
  191. CustomMembership.objects.create(person=self.jane, group=self.roll, date_joined=yesterday)
  192. CustomMembership.objects.create(person=self.jim, group=self.roll, date_joined=today)
  193. self.assertSequenceEqual(
  194. self.rock.custom_members.order_by('custom_person_related_name'),
  195. [self.jim, self.bob]
  196. )
  197. self.assertSequenceEqual(
  198. self.roll.custom_members.order_by('custom_person_related_name'),
  199. [self.jane, self.jim]
  200. )
  201. def test_query_first_model_by_intermediate_model_attribute(self):
  202. Membership.objects.create(
  203. person=self.jane, group=self.roll,
  204. invite_reason="She was just awesome."
  205. )
  206. Membership.objects.create(
  207. person=self.jim, group=self.roll,
  208. invite_reason="He is good."
  209. )
  210. Membership.objects.create(person=self.bob, group=self.roll)
  211. qs = Group.objects.filter(
  212. membership__invite_reason="She was just awesome."
  213. )
  214. self.assertQuerysetEqual(
  215. qs,
  216. ['Roll'],
  217. attrgetter("name")
  218. )
  219. def test_query_second_model_by_intermediate_model_attribute(self):
  220. Membership.objects.create(
  221. person=self.jane, group=self.roll,
  222. invite_reason="She was just awesome."
  223. )
  224. Membership.objects.create(
  225. person=self.jim, group=self.roll,
  226. invite_reason="He is good."
  227. )
  228. Membership.objects.create(person=self.bob, group=self.roll)
  229. qs = Person.objects.filter(
  230. membership__invite_reason="She was just awesome."
  231. )
  232. self.assertQuerysetEqual(
  233. qs,
  234. ['Jane'],
  235. attrgetter("name")
  236. )
  237. def test_query_model_by_related_model_name(self):
  238. Membership.objects.create(person=self.jim, group=self.rock)
  239. Membership.objects.create(person=self.jane, group=self.rock)
  240. Membership.objects.create(person=self.bob, group=self.roll)
  241. Membership.objects.create(person=self.jim, group=self.roll)
  242. Membership.objects.create(person=self.jane, group=self.roll)
  243. self.assertQuerysetEqual(
  244. Person.objects.filter(group__name="Rock"),
  245. ['Jane', 'Jim'],
  246. attrgetter("name")
  247. )
  248. def test_query_model_by_custom_related_name(self):
  249. CustomMembership.objects.create(person=self.bob, group=self.rock)
  250. CustomMembership.objects.create(person=self.jim, group=self.rock)
  251. self.assertQuerysetEqual(
  252. Person.objects.filter(custom__name="Rock"),
  253. ['Bob', 'Jim'],
  254. attrgetter("name")
  255. )
  256. def test_query_model_by_intermediate_can_return_non_unique_queryset(self):
  257. Membership.objects.create(person=self.jim, group=self.rock)
  258. Membership.objects.create(
  259. person=self.jane, group=self.rock,
  260. date_joined=datetime(2006, 1, 1)
  261. )
  262. Membership.objects.create(
  263. person=self.bob, group=self.roll,
  264. date_joined=datetime(2004, 1, 1))
  265. Membership.objects.create(person=self.jim, group=self.roll)
  266. Membership.objects.create(
  267. person=self.jane, group=self.roll,
  268. date_joined=datetime(2004, 1, 1))
  269. qs = Person.objects.filter(
  270. membership__date_joined__gt=datetime(2004, 1, 1)
  271. )
  272. self.assertQuerysetEqual(
  273. qs,
  274. ['Jane', 'Jim', 'Jim'],
  275. attrgetter("name")
  276. )
  277. def test_custom_related_name_forward_empty_qs(self):
  278. self.assertQuerysetEqual(
  279. self.rock.custom_members.all(),
  280. []
  281. )
  282. def test_custom_related_name_reverse_empty_qs(self):
  283. self.assertQuerysetEqual(
  284. self.bob.custom.all(),
  285. []
  286. )
  287. def test_custom_related_name_forward_non_empty_qs(self):
  288. CustomMembership.objects.create(person=self.bob, group=self.rock)
  289. CustomMembership.objects.create(person=self.jim, group=self.rock)
  290. self.assertQuerysetEqual(
  291. self.rock.custom_members.all(),
  292. ['Bob', 'Jim'],
  293. attrgetter("name")
  294. )
  295. def test_custom_related_name_reverse_non_empty_qs(self):
  296. CustomMembership.objects.create(person=self.bob, group=self.rock)
  297. CustomMembership.objects.create(person=self.jim, group=self.rock)
  298. self.assertQuerysetEqual(
  299. self.bob.custom.all(),
  300. ['Rock'],
  301. attrgetter("name")
  302. )
  303. def test_custom_related_name_doesnt_conflict_with_fky_related_name(self):
  304. c = CustomMembership.objects.create(person=self.bob, group=self.rock)
  305. self.assertSequenceEqual(self.bob.custom_person_related_name.all(), [c])
  306. def test_through_fields(self):
  307. """
  308. Relations with intermediary tables with multiple FKs
  309. to the M2M's ``to`` model are possible.
  310. """
  311. event = Event.objects.create(title='Rockwhale 2014')
  312. Invitation.objects.create(event=event, inviter=self.bob, invitee=self.jim)
  313. Invitation.objects.create(event=event, inviter=self.bob, invitee=self.jane)
  314. self.assertQuerysetEqual(
  315. event.invitees.all(),
  316. ['Jane', 'Jim'],
  317. attrgetter('name')
  318. )
  319. class M2mThroughReferentialTests(TestCase):
  320. def test_self_referential_empty_qs(self):
  321. tony = PersonSelfRefM2M.objects.create(name="Tony")
  322. self.assertQuerysetEqual(
  323. tony.friends.all(),
  324. []
  325. )
  326. def test_self_referential_non_symmetrical_first_side(self):
  327. tony = PersonSelfRefM2M.objects.create(name="Tony")
  328. chris = PersonSelfRefM2M.objects.create(name="Chris")
  329. Friendship.objects.create(
  330. first=tony, second=chris, date_friended=datetime.now()
  331. )
  332. self.assertQuerysetEqual(
  333. tony.friends.all(),
  334. ['Chris'],
  335. attrgetter("name")
  336. )
  337. def test_self_referential_non_symmetrical_second_side(self):
  338. tony = PersonSelfRefM2M.objects.create(name="Tony")
  339. chris = PersonSelfRefM2M.objects.create(name="Chris")
  340. Friendship.objects.create(
  341. first=tony, second=chris, date_friended=datetime.now()
  342. )
  343. self.assertQuerysetEqual(
  344. chris.friends.all(),
  345. []
  346. )
  347. def test_self_referential_non_symmetrical_clear_first_side(self):
  348. tony = PersonSelfRefM2M.objects.create(name="Tony")
  349. chris = PersonSelfRefM2M.objects.create(name="Chris")
  350. Friendship.objects.create(
  351. first=tony, second=chris, date_friended=datetime.now()
  352. )
  353. chris.friends.clear()
  354. self.assertQuerysetEqual(
  355. chris.friends.all(),
  356. []
  357. )
  358. # Since this isn't a symmetrical relation, Tony's friend link still exists.
  359. self.assertQuerysetEqual(
  360. tony.friends.all(),
  361. ['Chris'],
  362. attrgetter("name")
  363. )
  364. def test_self_referential_non_symmetrical_both(self):
  365. tony = PersonSelfRefM2M.objects.create(name="Tony")
  366. chris = PersonSelfRefM2M.objects.create(name="Chris")
  367. Friendship.objects.create(
  368. first=tony, second=chris, date_friended=datetime.now()
  369. )
  370. Friendship.objects.create(
  371. first=chris, second=tony, date_friended=datetime.now()
  372. )
  373. self.assertQuerysetEqual(
  374. tony.friends.all(),
  375. ['Chris'],
  376. attrgetter("name")
  377. )
  378. self.assertQuerysetEqual(
  379. chris.friends.all(),
  380. ['Tony'],
  381. attrgetter("name")
  382. )
  383. def test_through_fields_self_referential(self):
  384. john = Employee.objects.create(name='john')
  385. peter = Employee.objects.create(name='peter')
  386. mary = Employee.objects.create(name='mary')
  387. harry = Employee.objects.create(name='harry')
  388. Relationship.objects.create(source=john, target=peter, another=None)
  389. Relationship.objects.create(source=john, target=mary, another=None)
  390. Relationship.objects.create(source=john, target=harry, another=peter)
  391. self.assertQuerysetEqual(
  392. john.subordinates.all(),
  393. ['peter', 'mary', 'harry'],
  394. attrgetter('name')
  395. )
  396. def test_self_referential_symmetrical(self):
  397. tony = PersonSelfRefM2M.objects.create(name='Tony')
  398. chris = PersonSelfRefM2M.objects.create(name='Chris')
  399. SymmetricalFriendship.objects.create(
  400. first=tony, second=chris, date_friended=date.today(),
  401. )
  402. self.assertSequenceEqual(tony.sym_friends.all(), [chris])
  403. # Manually created symmetrical m2m relation doesn't add mirror entry
  404. # automatically.
  405. self.assertSequenceEqual(chris.sym_friends.all(), [])
  406. SymmetricalFriendship.objects.create(
  407. first=chris, second=tony, date_friended=date.today()
  408. )
  409. self.assertSequenceEqual(chris.sym_friends.all(), [tony])
  410. def test_add_on_symmetrical_m2m_with_intermediate_model(self):
  411. tony = PersonSelfRefM2M.objects.create(name='Tony')
  412. chris = PersonSelfRefM2M.objects.create(name='Chris')
  413. date_friended = date(2017, 1, 3)
  414. tony.sym_friends.add(chris, through_defaults={'date_friended': date_friended})
  415. self.assertSequenceEqual(tony.sym_friends.all(), [chris])
  416. self.assertSequenceEqual(chris.sym_friends.all(), [tony])
  417. friendship = tony.symmetricalfriendship_set.get()
  418. self.assertEqual(friendship.date_friended, date_friended)
  419. def test_set_on_symmetrical_m2m_with_intermediate_model(self):
  420. tony = PersonSelfRefM2M.objects.create(name='Tony')
  421. chris = PersonSelfRefM2M.objects.create(name='Chris')
  422. anne = PersonSelfRefM2M.objects.create(name='Anne')
  423. kate = PersonSelfRefM2M.objects.create(name='Kate')
  424. date_friended_add = date(2013, 1, 5)
  425. date_friended_set = date.today()
  426. tony.sym_friends.add(
  427. anne, chris,
  428. through_defaults={'date_friended': date_friended_add},
  429. )
  430. tony.sym_friends.set(
  431. [anne, kate],
  432. through_defaults={'date_friended': date_friended_set},
  433. )
  434. self.assertSequenceEqual(tony.sym_friends.all(), [anne, kate])
  435. self.assertSequenceEqual(anne.sym_friends.all(), [tony])
  436. self.assertSequenceEqual(kate.sym_friends.all(), [tony])
  437. self.assertEqual(
  438. kate.symmetricalfriendship_set.get().date_friended,
  439. date_friended_set,
  440. )
  441. # Date is preserved.
  442. self.assertEqual(
  443. anne.symmetricalfriendship_set.get().date_friended,
  444. date_friended_add,
  445. )
  446. # Recreate relationship.
  447. tony.sym_friends.set(
  448. [anne],
  449. clear=True,
  450. through_defaults={'date_friended': date_friended_set},
  451. )
  452. self.assertSequenceEqual(tony.sym_friends.all(), [anne])
  453. self.assertSequenceEqual(anne.sym_friends.all(), [tony])
  454. self.assertEqual(
  455. anne.symmetricalfriendship_set.get().date_friended,
  456. date_friended_set,
  457. )
  458. class M2mThroughToFieldsTests(TestCase):
  459. @classmethod
  460. def setUpTestData(cls):
  461. cls.pea = Ingredient.objects.create(iname='pea')
  462. cls.potato = Ingredient.objects.create(iname='potato')
  463. cls.tomato = Ingredient.objects.create(iname='tomato')
  464. cls.curry = Recipe.objects.create(rname='curry')
  465. RecipeIngredient.objects.create(recipe=cls.curry, ingredient=cls.potato)
  466. RecipeIngredient.objects.create(recipe=cls.curry, ingredient=cls.pea)
  467. RecipeIngredient.objects.create(recipe=cls.curry, ingredient=cls.tomato)
  468. def test_retrieval(self):
  469. # Forward retrieval
  470. self.assertSequenceEqual(self.curry.ingredients.all(), [self.pea, self.potato, self.tomato])
  471. # Backward retrieval
  472. self.assertEqual(self.tomato.recipes.get(), self.curry)
  473. def test_choices(self):
  474. field = Recipe._meta.get_field('ingredients')
  475. self.assertEqual(
  476. [choice[0] for choice in field.get_choices(include_blank=False)],
  477. ['pea', 'potato', 'tomato']
  478. )