PageRenderTime 56ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/django-1.5/tests/modeltests/many_to_one/tests.py

https://github.com/theosp/google_appengine
Python | 439 lines | 348 code | 34 blank | 57 comment | 1 complexity | a890d7bdad195a9eaa816f53cd8232ae MD5 | raw file
  1. from __future__ import absolute_import
  2. from copy import deepcopy
  3. from datetime import datetime
  4. from django.core.exceptions import MultipleObjectsReturned, FieldError
  5. from django.test import TestCase
  6. from django.utils import six
  7. from django.utils.translation import ugettext_lazy
  8. from .models import Article, Reporter
  9. class ManyToOneTests(TestCase):
  10. def setUp(self):
  11. # Create a few Reporters.
  12. self.r = Reporter(first_name='John', last_name='Smith', email='john@example.com')
  13. self.r.save()
  14. self.r2 = Reporter(first_name='Paul', last_name='Jones', email='paul@example.com')
  15. self.r2.save()
  16. # Create an Article.
  17. self.a = Article(id=None, headline="This is a test",
  18. pub_date=datetime(2005, 7, 27), reporter=self.r)
  19. self.a.save()
  20. def test_get(self):
  21. # Article objects have access to their related Reporter objects.
  22. r = self.a.reporter
  23. self.assertEqual(r.id, self.r.id)
  24. # These are strings instead of unicode strings because that's what was used in
  25. # the creation of this reporter (and we haven't refreshed the data from the
  26. # database, which always returns unicode strings).
  27. self.assertEqual((r.first_name, self.r.last_name), ('John', 'Smith'))
  28. def test_create(self):
  29. # You can also instantiate an Article by passing the Reporter's ID
  30. # instead of a Reporter object.
  31. a3 = Article(id=None, headline="Third article",
  32. pub_date=datetime(2005, 7, 27), reporter_id=self.r.id)
  33. a3.save()
  34. self.assertEqual(a3.reporter.id, self.r.id)
  35. # Similarly, the reporter ID can be a string.
  36. a4 = Article(id=None, headline="Fourth article",
  37. pub_date=datetime(2005, 7, 27), reporter_id=str(self.r.id))
  38. a4.save()
  39. self.assertEqual(repr(a4.reporter), "<Reporter: John Smith>")
  40. def test_add(self):
  41. # Create an Article via the Reporter object.
  42. new_article = self.r.article_set.create(headline="John's second story",
  43. pub_date=datetime(2005, 7, 29))
  44. self.assertEqual(repr(new_article), "<Article: John's second story>")
  45. self.assertEqual(new_article.reporter.id, self.r.id)
  46. # Create a new article, and add it to the article set.
  47. new_article2 = Article(headline="Paul's story", pub_date=datetime(2006, 1, 17))
  48. self.r.article_set.add(new_article2)
  49. self.assertEqual(new_article2.reporter.id, self.r.id)
  50. self.assertQuerysetEqual(self.r.article_set.all(),
  51. [
  52. "<Article: John's second story>",
  53. "<Article: Paul's story>",
  54. "<Article: This is a test>",
  55. ])
  56. # Add the same article to a different article set - check that it moves.
  57. self.r2.article_set.add(new_article2)
  58. self.assertEqual(new_article2.reporter.id, self.r2.id)
  59. self.assertQuerysetEqual(self.r2.article_set.all(), ["<Article: Paul's story>"])
  60. # Adding an object of the wrong type raises TypeError.
  61. with six.assertRaisesRegex(self, TypeError, "'Article' instance expected, got <Reporter.*"):
  62. self.r.article_set.add(self.r2)
  63. self.assertQuerysetEqual(self.r.article_set.all(),
  64. [
  65. "<Article: John's second story>",
  66. "<Article: This is a test>",
  67. ])
  68. def test_assign(self):
  69. new_article = self.r.article_set.create(headline="John's second story",
  70. pub_date=datetime(2005, 7, 29))
  71. new_article2 = self.r2.article_set.create(headline="Paul's story",
  72. pub_date=datetime(2006, 1, 17))
  73. # Assign the article to the reporter directly using the descriptor.
  74. new_article2.reporter = self.r
  75. new_article2.save()
  76. self.assertEqual(repr(new_article2.reporter), "<Reporter: John Smith>")
  77. self.assertEqual(new_article2.reporter.id, self.r.id)
  78. self.assertQuerysetEqual(self.r.article_set.all(), [
  79. "<Article: John's second story>",
  80. "<Article: Paul's story>",
  81. "<Article: This is a test>",
  82. ])
  83. self.assertQuerysetEqual(self.r2.article_set.all(), [])
  84. # Set the article back again using set descriptor.
  85. self.r2.article_set = [new_article, new_article2]
  86. self.assertQuerysetEqual(self.r.article_set.all(), ["<Article: This is a test>"])
  87. self.assertQuerysetEqual(self.r2.article_set.all(),
  88. [
  89. "<Article: John's second story>",
  90. "<Article: Paul's story>",
  91. ])
  92. # Funny case - assignment notation can only go so far; because the
  93. # ForeignKey cannot be null, existing members of the set must remain.
  94. self.r.article_set = [new_article]
  95. self.assertQuerysetEqual(self.r.article_set.all(),
  96. [
  97. "<Article: John's second story>",
  98. "<Article: This is a test>",
  99. ])
  100. self.assertQuerysetEqual(self.r2.article_set.all(), ["<Article: Paul's story>"])
  101. # Reporter cannot be null - there should not be a clear or remove method
  102. self.assertFalse(hasattr(self.r2.article_set, 'remove'))
  103. self.assertFalse(hasattr(self.r2.article_set, 'clear'))
  104. def test_selects(self):
  105. new_article = self.r.article_set.create(headline="John's second story",
  106. pub_date=datetime(2005, 7, 29))
  107. new_article2 = self.r2.article_set.create(headline="Paul's story",
  108. pub_date=datetime(2006, 1, 17))
  109. # Reporter objects have access to their related Article objects.
  110. self.assertQuerysetEqual(self.r.article_set.all(), [
  111. "<Article: John's second story>",
  112. "<Article: This is a test>",
  113. ])
  114. self.assertQuerysetEqual(self.r.article_set.filter(headline__startswith='This'),
  115. ["<Article: This is a test>"])
  116. self.assertEqual(self.r.article_set.count(), 2)
  117. self.assertEqual(self.r2.article_set.count(), 1)
  118. # Get articles by id
  119. self.assertQuerysetEqual(Article.objects.filter(id__exact=self.a.id),
  120. ["<Article: This is a test>"])
  121. self.assertQuerysetEqual(Article.objects.filter(pk=self.a.id),
  122. ["<Article: This is a test>"])
  123. # Query on an article property
  124. self.assertQuerysetEqual(Article.objects.filter(headline__startswith='This'),
  125. ["<Article: This is a test>"])
  126. # The API automatically follows relationships as far as you need.
  127. # Use double underscores to separate relationships.
  128. # This works as many levels deep as you want. There's no limit.
  129. # Find all Articles for any Reporter whose first name is "John".
  130. self.assertQuerysetEqual(Article.objects.filter(reporter__first_name__exact='John'),
  131. [
  132. "<Article: John's second story>",
  133. "<Article: This is a test>",
  134. ])
  135. # Check that implied __exact also works
  136. self.assertQuerysetEqual(Article.objects.filter(reporter__first_name='John'),
  137. [
  138. "<Article: John's second story>",
  139. "<Article: This is a test>",
  140. ])
  141. # Query twice over the related field.
  142. self.assertQuerysetEqual(
  143. Article.objects.filter(reporter__first_name__exact='John',
  144. reporter__last_name__exact='Smith'),
  145. [
  146. "<Article: John's second story>",
  147. "<Article: This is a test>",
  148. ])
  149. # The underlying query only makes one join when a related table is referenced twice.
  150. queryset = Article.objects.filter(reporter__first_name__exact='John',
  151. reporter__last_name__exact='Smith')
  152. self.assertNumQueries(1, list, queryset)
  153. self.assertEqual(queryset.query.get_compiler(queryset.db).as_sql()[0].count('INNER JOIN'), 1)
  154. # The automatically joined table has a predictable name.
  155. self.assertQuerysetEqual(
  156. Article.objects.filter(reporter__first_name__exact='John').extra(
  157. where=["many_to_one_reporter.last_name='Smith'"]),
  158. [
  159. "<Article: John's second story>",
  160. "<Article: This is a test>",
  161. ])
  162. # ... and should work fine with the unicode that comes out of forms.Form.cleaned_data
  163. self.assertQuerysetEqual(
  164. Article.objects.filter(reporter__first_name__exact='John'
  165. ).extra(where=["many_to_one_reporter.last_name='%s'" % 'Smith']),
  166. [
  167. "<Article: John's second story>",
  168. "<Article: This is a test>",
  169. ])
  170. # Find all Articles for a Reporter.
  171. # Use direct ID check, pk check, and object comparison
  172. self.assertQuerysetEqual(
  173. Article.objects.filter(reporter__id__exact=self.r.id),
  174. [
  175. "<Article: John's second story>",
  176. "<Article: This is a test>",
  177. ])
  178. self.assertQuerysetEqual(
  179. Article.objects.filter(reporter__pk=self.r.id),
  180. [
  181. "<Article: John's second story>",
  182. "<Article: This is a test>",
  183. ])
  184. self.assertQuerysetEqual(
  185. Article.objects.filter(reporter=self.r.id),
  186. [
  187. "<Article: John's second story>",
  188. "<Article: This is a test>",
  189. ])
  190. self.assertQuerysetEqual(
  191. Article.objects.filter(reporter=self.r),
  192. [
  193. "<Article: John's second story>",
  194. "<Article: This is a test>",
  195. ])
  196. self.assertQuerysetEqual(
  197. Article.objects.filter(reporter__in=[self.r.id,self.r2.id]).distinct(),
  198. [
  199. "<Article: John's second story>",
  200. "<Article: Paul's story>",
  201. "<Article: This is a test>",
  202. ])
  203. self.assertQuerysetEqual(
  204. Article.objects.filter(reporter__in=[self.r,self.r2]).distinct(),
  205. [
  206. "<Article: John's second story>",
  207. "<Article: Paul's story>",
  208. "<Article: This is a test>",
  209. ])
  210. # You can also use a queryset instead of a literal list of instances.
  211. # The queryset must be reduced to a list of values using values(),
  212. # then converted into a query
  213. self.assertQuerysetEqual(
  214. Article.objects.filter(
  215. reporter__in=Reporter.objects.filter(first_name='John').values('pk').query
  216. ).distinct(),
  217. [
  218. "<Article: John's second story>",
  219. "<Article: This is a test>",
  220. ])
  221. def test_reverse_selects(self):
  222. a3 = Article.objects.create(id=None, headline="Third article",
  223. pub_date=datetime(2005, 7, 27), reporter_id=self.r.id)
  224. a4 = Article.objects.create(id=None, headline="Fourth article",
  225. pub_date=datetime(2005, 7, 27), reporter_id=str(self.r.id))
  226. # Reporters can be queried
  227. self.assertQuerysetEqual(Reporter.objects.filter(id__exact=self.r.id),
  228. ["<Reporter: John Smith>"])
  229. self.assertQuerysetEqual(Reporter.objects.filter(pk=self.r.id),
  230. ["<Reporter: John Smith>"])
  231. self.assertQuerysetEqual(Reporter.objects.filter(first_name__startswith='John'),
  232. ["<Reporter: John Smith>"])
  233. # Reporters can query in opposite direction of ForeignKey definition
  234. self.assertQuerysetEqual(Reporter.objects.filter(article__id__exact=self.a.id),
  235. ["<Reporter: John Smith>"])
  236. self.assertQuerysetEqual(Reporter.objects.filter(article__pk=self.a.id),
  237. ["<Reporter: John Smith>"])
  238. self.assertQuerysetEqual(Reporter.objects.filter(article=self.a.id),
  239. ["<Reporter: John Smith>"])
  240. self.assertQuerysetEqual(Reporter.objects.filter(article=self.a),
  241. ["<Reporter: John Smith>"])
  242. self.assertQuerysetEqual(
  243. Reporter.objects.filter(article__in=[self.a.id,a3.id]).distinct(),
  244. ["<Reporter: John Smith>"])
  245. self.assertQuerysetEqual(
  246. Reporter.objects.filter(article__in=[self.a.id,a3]).distinct(),
  247. ["<Reporter: John Smith>"])
  248. self.assertQuerysetEqual(
  249. Reporter.objects.filter(article__in=[self.a,a3]).distinct(),
  250. ["<Reporter: John Smith>"])
  251. self.assertQuerysetEqual(
  252. Reporter.objects.filter(article__headline__startswith='T'),
  253. ["<Reporter: John Smith>", "<Reporter: John Smith>"])
  254. self.assertQuerysetEqual(
  255. Reporter.objects.filter(article__headline__startswith='T').distinct(),
  256. ["<Reporter: John Smith>"])
  257. # Counting in the opposite direction works in conjunction with distinct()
  258. self.assertEqual(
  259. Reporter.objects.filter(article__headline__startswith='T').count(), 2)
  260. self.assertEqual(
  261. Reporter.objects.filter(article__headline__startswith='T').distinct().count(), 1)
  262. # Queries can go round in circles.
  263. self.assertQuerysetEqual(
  264. Reporter.objects.filter(article__reporter__first_name__startswith='John'),
  265. [
  266. "<Reporter: John Smith>",
  267. "<Reporter: John Smith>",
  268. "<Reporter: John Smith>",
  269. ])
  270. self.assertQuerysetEqual(
  271. Reporter.objects.filter(article__reporter__first_name__startswith='John').distinct(),
  272. ["<Reporter: John Smith>"])
  273. self.assertQuerysetEqual(
  274. Reporter.objects.filter(article__reporter__exact=self.r).distinct(),
  275. ["<Reporter: John Smith>"])
  276. # Check that implied __exact also works.
  277. self.assertQuerysetEqual(
  278. Reporter.objects.filter(article__reporter=self.r).distinct(),
  279. ["<Reporter: John Smith>"])
  280. # It's possible to use values() calls across many-to-one relations.
  281. # (Note, too, that we clear the ordering here so as not to drag the
  282. # 'headline' field into the columns being used to determine uniqueness)
  283. d = {'reporter__first_name': 'John', 'reporter__last_name': 'Smith'}
  284. self.assertEqual([d],
  285. list(Article.objects.filter(reporter=self.r).distinct().order_by()
  286. .values('reporter__first_name', 'reporter__last_name')))
  287. def test_select_related(self):
  288. # Check that Article.objects.select_related().dates() works properly when
  289. # there are multiple Articles with the same date but different foreign-key
  290. # objects (Reporters).
  291. r1 = Reporter.objects.create(first_name='Mike', last_name='Royko', email='royko@suntimes.com')
  292. r2 = Reporter.objects.create(first_name='John', last_name='Kass', email='jkass@tribune.com')
  293. a1 = Article.objects.create(headline='First', pub_date=datetime(1980, 4, 23), reporter=r1)
  294. a2 = Article.objects.create(headline='Second', pub_date=datetime(1980, 4, 23), reporter=r2)
  295. self.assertEqual(list(Article.objects.select_related().dates('pub_date', 'day')),
  296. [
  297. datetime(1980, 4, 23, 0, 0),
  298. datetime(2005, 7, 27, 0, 0),
  299. ])
  300. self.assertEqual(list(Article.objects.select_related().dates('pub_date', 'month')),
  301. [
  302. datetime(1980, 4, 1, 0, 0),
  303. datetime(2005, 7, 1, 0, 0),
  304. ])
  305. self.assertEqual(list(Article.objects.select_related().dates('pub_date', 'year')),
  306. [
  307. datetime(1980, 1, 1, 0, 0),
  308. datetime(2005, 1, 1, 0, 0),
  309. ])
  310. def test_delete(self):
  311. new_article = self.r.article_set.create(headline="John's second story",
  312. pub_date=datetime(2005, 7, 29))
  313. new_article2 = self.r2.article_set.create(headline="Paul's story",
  314. pub_date=datetime(2006, 1, 17))
  315. a3 = Article.objects.create(id=None, headline="Third article",
  316. pub_date=datetime(2005, 7, 27), reporter_id=self.r.id)
  317. a4 = Article.objects.create(id=None, headline="Fourth article",
  318. pub_date=datetime(2005, 7, 27), reporter_id=str(self.r.id))
  319. # If you delete a reporter, his articles will be deleted.
  320. self.assertQuerysetEqual(Article.objects.all(),
  321. [
  322. "<Article: Fourth article>",
  323. "<Article: John's second story>",
  324. "<Article: Paul's story>",
  325. "<Article: Third article>",
  326. "<Article: This is a test>",
  327. ])
  328. self.assertQuerysetEqual(Reporter.objects.order_by('first_name'),
  329. [
  330. "<Reporter: John Smith>",
  331. "<Reporter: Paul Jones>",
  332. ])
  333. self.r2.delete()
  334. self.assertQuerysetEqual(Article.objects.all(),
  335. [
  336. "<Article: Fourth article>",
  337. "<Article: John's second story>",
  338. "<Article: Third article>",
  339. "<Article: This is a test>",
  340. ])
  341. self.assertQuerysetEqual(Reporter.objects.order_by('first_name'),
  342. ["<Reporter: John Smith>"])
  343. # You can delete using a JOIN in the query.
  344. Reporter.objects.filter(article__headline__startswith='This').delete()
  345. self.assertQuerysetEqual(Reporter.objects.all(), [])
  346. self.assertQuerysetEqual(Article.objects.all(), [])
  347. def test_regression_12876(self):
  348. # Regression for #12876 -- Model methods that include queries that
  349. # recursive don't cause recursion depth problems under deepcopy.
  350. self.r.cached_query = Article.objects.filter(reporter=self.r)
  351. self.assertEqual(repr(deepcopy(self.r)), "<Reporter: John Smith>")
  352. def test_explicit_fk(self):
  353. # Create a new Article with get_or_create using an explicit value
  354. # for a ForeignKey.
  355. a2, created = Article.objects.get_or_create(id=None,
  356. headline="John's second test",
  357. pub_date=datetime(2011, 5, 7),
  358. reporter_id=self.r.id)
  359. self.assertTrue(created)
  360. self.assertEqual(a2.reporter.id, self.r.id)
  361. # You can specify filters containing the explicit FK value.
  362. self.assertQuerysetEqual(
  363. Article.objects.filter(reporter_id__exact=self.r.id),
  364. [
  365. "<Article: John's second test>",
  366. "<Article: This is a test>",
  367. ])
  368. # Create an Article by Paul for the same date.
  369. a3 = Article.objects.create(id=None, headline="Paul's commentary",
  370. pub_date=datetime(2011, 5, 7),
  371. reporter_id=self.r2.id)
  372. self.assertEqual(a3.reporter.id, self.r2.id)
  373. # Get should respect explicit foreign keys as well.
  374. self.assertRaises(MultipleObjectsReturned,
  375. Article.objects.get, reporter_id=self.r.id)
  376. self.assertEqual(repr(a3),
  377. repr(Article.objects.get(reporter_id=self.r2.id,
  378. pub_date=datetime(2011, 5, 7))))
  379. def test_manager_class_caching(self):
  380. r1 = Reporter.objects.create(first_name='Mike')
  381. r2 = Reporter.objects.create(first_name='John')
  382. # Same twice
  383. self.assertTrue(r1.article_set.__class__ is r1.article_set.__class__)
  384. # Same as each other
  385. self.assertTrue(r1.article_set.__class__ is r2.article_set.__class__)
  386. def test_create_relation_with_ugettext_lazy(self):
  387. reporter = Reporter.objects.create(first_name='John',
  388. last_name='Smith',
  389. email='john.smith@example.com')
  390. lazy = ugettext_lazy('test')
  391. reporter.article_set.create(headline=lazy,
  392. pub_date=datetime(2011, 6, 10))
  393. notlazy = six.text_type(lazy)
  394. article = reporter.article_set.get()
  395. self.assertEqual(article.headline, notlazy)
  396. def test_values_list_exception(self):
  397. expected_message = "Cannot resolve keyword 'notafield' into field. Choices are: %s"
  398. self.assertRaisesMessage(FieldError,
  399. expected_message % ', '.join(Reporter._meta.get_all_field_names()),
  400. Article.objects.values_list,
  401. 'reporter__notafield')
  402. self.assertRaisesMessage(FieldError,
  403. expected_message % ', '.join(['EXTRA',] + Article._meta.get_all_field_names()),
  404. Article.objects.extra(select={'EXTRA': 'EXTRA_SELECT'}).values_list,
  405. 'notafield')