PageRenderTime 36ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/modeltests/many_to_many/tests.py

https://code.google.com/p/mango-py/
Python | 384 lines | 327 code | 25 blank | 32 comment | 0 complexity | f19bce26e2b680d4a9bbd3b49ef26010 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. from django.test import TestCase
  2. from models import Article, Publication
  3. class ManyToManyTests(TestCase):
  4. def setUp(self):
  5. # Create a couple of Publications.
  6. self.p1 = Publication.objects.create(id=None, title='The Python Journal')
  7. self.p2 = Publication.objects.create(id=None, title='Science News')
  8. self.p3 = Publication.objects.create(id=None, title='Science Weekly')
  9. self.p4 = Publication.objects.create(title='Highlights for Children')
  10. self.a1 = Article.objects.create(id=None, headline='Django lets you build Web apps easily')
  11. self.a1.publications.add(self.p1)
  12. self.a2 = Article.objects.create(id=None, headline='NASA uses Python')
  13. self.a2.publications.add(self.p1, self.p2, self.p3, self.p4)
  14. self.a3 = Article.objects.create(headline='NASA finds intelligent life on Earth')
  15. self.a3.publications.add(self.p2)
  16. self.a4 = Article.objects.create(headline='Oxygen-free diet works wonders')
  17. self.a4.publications.add(self.p2)
  18. def test_add(self):
  19. # Create an Article.
  20. a5 = Article(id=None, headline='Django lets you reate Web apps easily')
  21. # You can't associate it with a Publication until it's been saved.
  22. self.assertRaises(ValueError, getattr, a5, 'publications')
  23. # Save it!
  24. a5.save()
  25. # Associate the Article with a Publication.
  26. a5.publications.add(self.p1)
  27. self.assertQuerysetEqual(a5.publications.all(),
  28. ['<Publication: The Python Journal>'])
  29. # Create another Article, and set it to appear in both Publications.
  30. a6 = Article(id=None, headline='ESA uses Python')
  31. a6.save()
  32. a6.publications.add(self.p1, self.p2)
  33. a6.publications.add(self.p3)
  34. # Adding a second time is OK
  35. a6.publications.add(self.p3)
  36. self.assertQuerysetEqual(a6.publications.all(),
  37. [
  38. '<Publication: Science News>',
  39. '<Publication: Science Weekly>',
  40. '<Publication: The Python Journal>',
  41. ])
  42. # Adding an object of the wrong type raises TypeError
  43. self.assertRaises(TypeError, a6.publications.add, a5)
  44. # Add a Publication directly via publications.add by using keyword arguments.
  45. p4 = a6.publications.create(title='Highlights for Adults')
  46. self.assertQuerysetEqual(a6.publications.all(),
  47. [
  48. '<Publication: Highlights for Adults>',
  49. '<Publication: Science News>',
  50. '<Publication: Science Weekly>',
  51. '<Publication: The Python Journal>',
  52. ])
  53. def test_reverse_add(self):
  54. # Adding via the 'other' end of an m2m
  55. a5 = Article(headline='NASA finds intelligent life on Mars')
  56. a5.save()
  57. self.p2.article_set.add(a5)
  58. self.assertQuerysetEqual(self.p2.article_set.all(),
  59. [
  60. '<Article: NASA finds intelligent life on Earth>',
  61. '<Article: NASA finds intelligent life on Mars>',
  62. '<Article: NASA uses Python>',
  63. '<Article: Oxygen-free diet works wonders>',
  64. ])
  65. self.assertQuerysetEqual(a5.publications.all(),
  66. ['<Publication: Science News>'])
  67. # Adding via the other end using keywords
  68. new_article = self.p2.article_set.create(headline='Carbon-free diet works wonders')
  69. self.assertQuerysetEqual(
  70. self.p2.article_set.all(),
  71. [
  72. '<Article: Carbon-free diet works wonders>',
  73. '<Article: NASA finds intelligent life on Earth>',
  74. '<Article: NASA finds intelligent life on Mars>',
  75. '<Article: NASA uses Python>',
  76. '<Article: Oxygen-free diet works wonders>',
  77. ])
  78. a6 = self.p2.article_set.all()[3]
  79. self.assertQuerysetEqual(a6.publications.all(),
  80. [
  81. '<Publication: Highlights for Children>',
  82. '<Publication: Science News>',
  83. '<Publication: Science Weekly>',
  84. '<Publication: The Python Journal>',
  85. ])
  86. def test_related_sets(self):
  87. # Article objects have access to their related Publication objects.
  88. self.assertQuerysetEqual(self.a1.publications.all(),
  89. ['<Publication: The Python Journal>'])
  90. self.assertQuerysetEqual(self.a2.publications.all(),
  91. [
  92. '<Publication: Highlights for Children>',
  93. '<Publication: Science News>',
  94. '<Publication: Science Weekly>',
  95. '<Publication: The Python Journal>',
  96. ])
  97. # Publication objects have access to their related Article objects.
  98. self.assertQuerysetEqual(self.p2.article_set.all(),
  99. [
  100. '<Article: NASA finds intelligent life on Earth>',
  101. '<Article: NASA uses Python>',
  102. '<Article: Oxygen-free diet works wonders>',
  103. ])
  104. self.assertQuerysetEqual(self.p1.article_set.all(),
  105. [
  106. '<Article: Django lets you build Web apps easily>',
  107. '<Article: NASA uses Python>',
  108. ])
  109. self.assertQuerysetEqual(Publication.objects.get(id=self.p4.id).article_set.all(),
  110. ['<Article: NASA uses Python>'])
  111. def test_selects(self):
  112. # We can perform kwarg queries across m2m relationships
  113. self.assertQuerysetEqual(
  114. Article.objects.filter(publications__id__exact=self.p1.id),
  115. [
  116. '<Article: Django lets you build Web apps easily>',
  117. '<Article: NASA uses Python>',
  118. ])
  119. self.assertQuerysetEqual(
  120. Article.objects.filter(publications__pk=self.p1.id),
  121. [
  122. '<Article: Django lets you build Web apps easily>',
  123. '<Article: NASA uses Python>',
  124. ])
  125. self.assertQuerysetEqual(
  126. Article.objects.filter(publications=self.p1.id),
  127. [
  128. '<Article: Django lets you build Web apps easily>',
  129. '<Article: NASA uses Python>',
  130. ])
  131. self.assertQuerysetEqual(
  132. Article.objects.filter(publications=self.p1),
  133. [
  134. '<Article: Django lets you build Web apps easily>',
  135. '<Article: NASA uses Python>',
  136. ])
  137. self.assertQuerysetEqual(
  138. Article.objects.filter(publications__title__startswith="Science"),
  139. [
  140. '<Article: NASA finds intelligent life on Earth>',
  141. '<Article: NASA uses Python>',
  142. '<Article: NASA uses Python>',
  143. '<Article: Oxygen-free diet works wonders>',
  144. ])
  145. self.assertQuerysetEqual(
  146. Article.objects.filter(publications__title__startswith="Science").distinct(),
  147. [
  148. '<Article: NASA finds intelligent life on Earth>',
  149. '<Article: NASA uses Python>',
  150. '<Article: Oxygen-free diet works wonders>',
  151. ])
  152. # The count() function respects distinct() as well.
  153. self.assertEqual(Article.objects.filter(publications__title__startswith="Science").count(), 4)
  154. self.assertEqual(Article.objects.filter(publications__title__startswith="Science").distinct().count(), 3)
  155. self.assertQuerysetEqual(
  156. Article.objects.filter(publications__in=[self.p1.id,self.p2.id]).distinct(),
  157. [
  158. '<Article: Django lets you build Web apps easily>',
  159. '<Article: NASA finds intelligent life on Earth>',
  160. '<Article: NASA uses Python>',
  161. '<Article: Oxygen-free diet works wonders>',
  162. ])
  163. self.assertQuerysetEqual(
  164. Article.objects.filter(publications__in=[self.p1.id,self.p2]).distinct(),
  165. [
  166. '<Article: Django lets you build Web apps easily>',
  167. '<Article: NASA finds intelligent life on Earth>',
  168. '<Article: NASA uses Python>',
  169. '<Article: Oxygen-free diet works wonders>',
  170. ])
  171. self.assertQuerysetEqual(
  172. Article.objects.filter(publications__in=[self.p1,self.p2]).distinct(),
  173. [
  174. '<Article: Django lets you build Web apps easily>',
  175. '<Article: NASA finds intelligent life on Earth>',
  176. '<Article: NASA uses Python>',
  177. '<Article: Oxygen-free diet works wonders>',
  178. ])
  179. # Excluding a related item works as you would expect, too (although the SQL
  180. # involved is a little complex).
  181. self.assertQuerysetEqual(Article.objects.exclude(publications=self.p2),
  182. ['<Article: Django lets you build Web apps easily>'])
  183. def test_reverse_selects(self):
  184. # Reverse m2m queries are supported (i.e., starting at the table that
  185. # doesn't have a ManyToManyField).
  186. self.assertQuerysetEqual(Publication.objects.filter(id__exact=self.p1.id),
  187. ['<Publication: The Python Journal>'])
  188. self.assertQuerysetEqual(Publication.objects.filter(pk=self.p1.id),
  189. ['<Publication: The Python Journal>'])
  190. self.assertQuerysetEqual(
  191. Publication.objects.filter(article__headline__startswith="NASA"),
  192. [
  193. '<Publication: Highlights for Children>',
  194. '<Publication: Science News>',
  195. '<Publication: Science News>',
  196. '<Publication: Science Weekly>',
  197. '<Publication: The Python Journal>',
  198. ])
  199. self.assertQuerysetEqual(Publication.objects.filter(article__id__exact=self.a1.id),
  200. ['<Publication: The Python Journal>'])
  201. self.assertQuerysetEqual(Publication.objects.filter(article__pk=self.a1.id),
  202. ['<Publication: The Python Journal>'])
  203. self.assertQuerysetEqual(Publication.objects.filter(article=self.a1.id),
  204. ['<Publication: The Python Journal>'])
  205. self.assertQuerysetEqual(Publication.objects.filter(article=self.a1),
  206. ['<Publication: The Python Journal>'])
  207. self.assertQuerysetEqual(
  208. Publication.objects.filter(article__in=[self.a1.id,self.a2.id]).distinct(),
  209. [
  210. '<Publication: Highlights for Children>',
  211. '<Publication: Science News>',
  212. '<Publication: Science Weekly>',
  213. '<Publication: The Python Journal>',
  214. ])
  215. self.assertQuerysetEqual(
  216. Publication.objects.filter(article__in=[self.a1.id,self.a2]).distinct(),
  217. [
  218. '<Publication: Highlights for Children>',
  219. '<Publication: Science News>',
  220. '<Publication: Science Weekly>',
  221. '<Publication: The Python Journal>',
  222. ])
  223. self.assertQuerysetEqual(
  224. Publication.objects.filter(article__in=[self.a1,self.a2]).distinct(),
  225. [
  226. '<Publication: Highlights for Children>',
  227. '<Publication: Science News>',
  228. '<Publication: Science Weekly>',
  229. '<Publication: The Python Journal>',
  230. ])
  231. def test_delete(self):
  232. # If we delete a Publication, its Articles won't be able to access it.
  233. self.p1.delete()
  234. self.assertQuerysetEqual(Publication.objects.all(),
  235. [
  236. '<Publication: Highlights for Children>',
  237. '<Publication: Science News>',
  238. '<Publication: Science Weekly>',
  239. ])
  240. self.assertQuerysetEqual(self.a1.publications.all(), [])
  241. # If we delete an Article, its Publications won't be able to access it.
  242. self.a2.delete()
  243. self.assertQuerysetEqual(Article.objects.all(),
  244. [
  245. '<Article: Django lets you build Web apps easily>',
  246. '<Article: NASA finds intelligent life on Earth>',
  247. '<Article: Oxygen-free diet works wonders>',
  248. ])
  249. self.assertQuerysetEqual(self.p2.article_set.all(),
  250. [
  251. '<Article: NASA finds intelligent life on Earth>',
  252. '<Article: Oxygen-free diet works wonders>',
  253. ])
  254. def test_bulk_delete(self):
  255. # Bulk delete some Publications - references to deleted publications should go
  256. Publication.objects.filter(title__startswith='Science').delete()
  257. self.assertQuerysetEqual(Publication.objects.all(),
  258. [
  259. '<Publication: Highlights for Children>',
  260. '<Publication: The Python Journal>',
  261. ])
  262. self.assertQuerysetEqual(Article.objects.all(),
  263. [
  264. '<Article: Django lets you build Web apps easily>',
  265. '<Article: NASA finds intelligent life on Earth>',
  266. '<Article: NASA uses Python>',
  267. '<Article: Oxygen-free diet works wonders>',
  268. ])
  269. self.assertQuerysetEqual(self.a2.publications.all(),
  270. [
  271. '<Publication: Highlights for Children>',
  272. '<Publication: The Python Journal>',
  273. ])
  274. # Bulk delete some articles - references to deleted objects should go
  275. q = Article.objects.filter(headline__startswith='Django')
  276. self.assertQuerysetEqual(q, ['<Article: Django lets you build Web apps easily>'])
  277. q.delete()
  278. # After the delete, the QuerySet cache needs to be cleared,
  279. # and the referenced objects should be gone
  280. self.assertQuerysetEqual(q, [])
  281. self.assertQuerysetEqual(self.p1.article_set.all(),
  282. ['<Article: NASA uses Python>'])
  283. def test_remove(self):
  284. # Removing publication from an article:
  285. self.assertQuerysetEqual(self.p2.article_set.all(),
  286. [
  287. '<Article: NASA finds intelligent life on Earth>',
  288. '<Article: NASA uses Python>',
  289. '<Article: Oxygen-free diet works wonders>',
  290. ])
  291. self.a4.publications.remove(self.p2)
  292. self.assertQuerysetEqual(self.p2.article_set.all(),
  293. [
  294. '<Article: NASA finds intelligent life on Earth>',
  295. '<Article: NASA uses Python>',
  296. ])
  297. self.assertQuerysetEqual(self.a4.publications.all(), [])
  298. # And from the other end
  299. self.p2.article_set.remove(self.a3)
  300. self.assertQuerysetEqual(self.p2.article_set.all(),
  301. [
  302. '<Article: NASA uses Python>',
  303. ])
  304. self.assertQuerysetEqual(self.a3.publications.all(), [])
  305. def test_assign(self):
  306. # Relation sets can be assigned. Assignment clears any existing set members
  307. self.p2.article_set = [self.a4, self.a3]
  308. self.assertQuerysetEqual(self.p2.article_set.all(),
  309. [
  310. '<Article: NASA finds intelligent life on Earth>',
  311. '<Article: Oxygen-free diet works wonders>',
  312. ])
  313. self.assertQuerysetEqual(self.a4.publications.all(),
  314. ['<Publication: Science News>'])
  315. self.a4.publications = [self.p3.id]
  316. self.assertQuerysetEqual(self.p2.article_set.all(),
  317. ['<Article: NASA finds intelligent life on Earth>'])
  318. self.assertQuerysetEqual(self.a4.publications.all(),
  319. ['<Publication: Science Weekly>'])
  320. # An alternate to calling clear() is to assign the empty set
  321. self.p2.article_set = []
  322. self.assertQuerysetEqual(self.p2.article_set.all(), [])
  323. self.a4.publications = []
  324. self.assertQuerysetEqual(self.a4.publications.all(), [])
  325. def test_assign_ids(self):
  326. # Relation sets can also be set using primary key values
  327. self.p2.article_set = [self.a4.id, self.a3.id]
  328. self.assertQuerysetEqual(self.p2.article_set.all(),
  329. [
  330. '<Article: NASA finds intelligent life on Earth>',
  331. '<Article: Oxygen-free diet works wonders>',
  332. ])
  333. self.assertQuerysetEqual(self.a4.publications.all(),
  334. ['<Publication: Science News>'])
  335. self.a4.publications = [self.p3.id]
  336. self.assertQuerysetEqual(self.p2.article_set.all(),
  337. ['<Article: NASA finds intelligent life on Earth>'])
  338. self.assertQuerysetEqual(self.a4.publications.all(),
  339. ['<Publication: Science Weekly>'])
  340. def test_clear(self):
  341. # Relation sets can be cleared:
  342. self.p2.article_set.clear()
  343. self.assertQuerysetEqual(self.p2.article_set.all(), [])
  344. self.assertQuerysetEqual(self.a4.publications.all(), [])
  345. # And you can clear from the other end
  346. self.p2.article_set.add(self.a3, self.a4)
  347. self.assertQuerysetEqual(self.p2.article_set.all(),
  348. [
  349. '<Article: NASA finds intelligent life on Earth>',
  350. '<Article: Oxygen-free diet works wonders>',
  351. ])
  352. self.assertQuerysetEqual(self.a4.publications.all(),
  353. [
  354. '<Publication: Science News>',
  355. ])
  356. self.a4.publications.clear()
  357. self.assertQuerysetEqual(self.a4.publications.all(), [])
  358. self.assertQuerysetEqual(self.p2.article_set.all(),
  359. ['<Article: NASA finds intelligent life on Earth>'])