tests.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. import datetime
  2. from copy import deepcopy
  3. from django.core.exceptions import FieldError, MultipleObjectsReturned
  4. from django.db import models, transaction
  5. from django.db.utils import IntegrityError
  6. from django.test import TestCase
  7. from django.utils import six
  8. from django.utils.deprecation import RemovedInDjango20Warning
  9. from django.utils.translation import ugettext_lazy
  10. from .models import (
  11. Article, Category, Child, City, District, First, Parent, Record, Relation,
  12. Reporter, School, Student, Third, ToFieldChild,
  13. )
  14. class ManyToOneTests(TestCase):
  15. def setUp(self):
  16. # Create a few Reporters.
  17. self.r = Reporter(first_name='John', last_name='Smith', email='john@example.com')
  18. self.r.save()
  19. self.r2 = Reporter(first_name='Paul', last_name='Jones', email='paul@example.com')
  20. self.r2.save()
  21. # Create an Article.
  22. self.a = Article(headline="This is a test", pub_date=datetime.date(2005, 7, 27), reporter=self.r)
  23. self.a.save()
  24. def test_get(self):
  25. # Article objects have access to their related Reporter objects.
  26. r = self.a.reporter
  27. self.assertEqual(r.id, self.r.id)
  28. # These are strings instead of unicode strings because that's what was used in
  29. # the creation of this reporter (and we haven't refreshed the data from the
  30. # database, which always returns unicode strings).
  31. self.assertEqual((r.first_name, self.r.last_name), ('John', 'Smith'))
  32. def test_create(self):
  33. # You can also instantiate an Article by passing the Reporter's ID
  34. # instead of a Reporter object.
  35. a3 = Article(headline="Third article", pub_date=datetime.date(2005, 7, 27), reporter_id=self.r.id)
  36. a3.save()
  37. self.assertEqual(a3.reporter.id, self.r.id)
  38. # Similarly, the reporter ID can be a string.
  39. a4 = Article(headline="Fourth article", pub_date=datetime.date(2005, 7, 27), reporter_id=str(self.r.id))
  40. a4.save()
  41. self.assertEqual(repr(a4.reporter), "<Reporter: John Smith>")
  42. def test_add(self):
  43. # Create an Article via the Reporter object.
  44. new_article = self.r.article_set.create(headline="John's second story", pub_date=datetime.date(2005, 7, 29))
  45. self.assertEqual(repr(new_article), "<Article: John's second story>")
  46. self.assertEqual(new_article.reporter.id, self.r.id)
  47. # Create a new article, and add it to the article set.
  48. new_article2 = Article(headline="Paul's story", pub_date=datetime.date(2006, 1, 17))
  49. msg = "<Article: Paul's story> instance isn't saved. Use bulk=False or save the object first."
  50. with self.assertRaisesMessage(ValueError, msg):
  51. self.r.article_set.add(new_article2)
  52. self.r.article_set.add(new_article2, bulk=False)
  53. self.assertEqual(new_article2.reporter.id, self.r.id)
  54. self.assertQuerysetEqual(
  55. self.r.article_set.all(),
  56. ["<Article: John's second story>", "<Article: Paul's story>", "<Article: This is a test>"]
  57. )
  58. # Add the same article to a different article set - check that it moves.
  59. self.r2.article_set.add(new_article2)
  60. self.assertEqual(new_article2.reporter.id, self.r2.id)
  61. self.assertQuerysetEqual(self.r2.article_set.all(), ["<Article: Paul's story>"])
  62. # Adding an object of the wrong type raises TypeError.
  63. with transaction.atomic():
  64. with six.assertRaisesRegex(self, TypeError,
  65. "'Article' instance expected, got <Reporter.*"):
  66. self.r.article_set.add(self.r2)
  67. self.assertQuerysetEqual(
  68. self.r.article_set.all(),
  69. ["<Article: John's second story>", "<Article: This is a test>"]
  70. )
  71. def test_set(self):
  72. new_article = self.r.article_set.create(headline="John's second story", pub_date=datetime.date(2005, 7, 29))
  73. new_article2 = self.r2.article_set.create(headline="Paul's story", pub_date=datetime.date(2006, 1, 17))
  74. # Assign the article to the reporter.
  75. new_article2.reporter = self.r
  76. new_article2.save()
  77. self.assertEqual(repr(new_article2.reporter), "<Reporter: John Smith>")
  78. self.assertEqual(new_article2.reporter.id, self.r.id)
  79. self.assertQuerysetEqual(self.r.article_set.all(), [
  80. "<Article: John's second story>",
  81. "<Article: Paul's story>",
  82. "<Article: This is a test>",
  83. ])
  84. self.assertQuerysetEqual(self.r2.article_set.all(), [])
  85. # Set the article back again.
  86. self.r2.article_set.set([new_article, new_article2])
  87. self.assertQuerysetEqual(self.r.article_set.all(), ["<Article: This is a test>"])
  88. self.assertQuerysetEqual(
  89. self.r2.article_set.all(),
  90. ["<Article: John's second story>", "<Article: Paul's story>"]
  91. )
  92. # Funny case - because the ForeignKey cannot be null,
  93. # existing members of the set must remain.
  94. self.r.article_set.set([new_article])
  95. self.assertQuerysetEqual(
  96. self.r.article_set.all(),
  97. ["<Article: John's second story>", "<Article: This is a test>"]
  98. )
  99. self.assertQuerysetEqual(self.r2.article_set.all(), ["<Article: Paul's story>"])
  100. def test_reverse_assignment_deprecation(self):
  101. msg = (
  102. "Direct assignment to the reverse side of a related set is "
  103. "deprecated due to the implicit save() that happens. Use "
  104. "article_set.set() instead."
  105. )
  106. with self.assertRaisesMessage(RemovedInDjango20Warning, msg):
  107. self.r2.article_set = []
  108. def test_assign(self):
  109. new_article = self.r.article_set.create(headline="John's second story", pub_date=datetime.date(2005, 7, 29))
  110. new_article2 = self.r2.article_set.create(headline="Paul's story", pub_date=datetime.date(2006, 1, 17))
  111. # Assign the article to the reporter directly using the descriptor.
  112. new_article2.reporter = self.r
  113. new_article2.save()
  114. self.assertEqual(repr(new_article2.reporter), "<Reporter: John Smith>")
  115. self.assertEqual(new_article2.reporter.id, self.r.id)
  116. self.assertQuerysetEqual(self.r.article_set.all(), [
  117. "<Article: John's second story>",
  118. "<Article: Paul's story>",
  119. "<Article: This is a test>",
  120. ])
  121. self.assertQuerysetEqual(self.r2.article_set.all(), [])
  122. # Set the article back again using set() method.
  123. self.r2.article_set.set([new_article, new_article2])
  124. self.assertQuerysetEqual(self.r.article_set.all(), ["<Article: This is a test>"])
  125. self.assertQuerysetEqual(
  126. self.r2.article_set.all(),
  127. ["<Article: John's second story>", "<Article: Paul's story>"]
  128. )
  129. # Because the ForeignKey cannot be null, existing members of the set
  130. # must remain.
  131. self.r.article_set.set([new_article])
  132. self.assertQuerysetEqual(
  133. self.r.article_set.all(),
  134. ["<Article: John's second story>", "<Article: This is a test>"]
  135. )
  136. self.assertQuerysetEqual(self.r2.article_set.all(), ["<Article: Paul's story>"])
  137. # Reporter cannot be null - there should not be a clear or remove method
  138. self.assertFalse(hasattr(self.r2.article_set, 'remove'))
  139. self.assertFalse(hasattr(self.r2.article_set, 'clear'))
  140. def test_selects(self):
  141. self.r.article_set.create(headline="John's second story", pub_date=datetime.date(2005, 7, 29))
  142. self.r2.article_set.create(headline="Paul's story", pub_date=datetime.date(2006, 1, 17))
  143. # Reporter objects have access to their related Article objects.
  144. self.assertQuerysetEqual(self.r.article_set.all(), [
  145. "<Article: John's second story>",
  146. "<Article: This is a test>",
  147. ])
  148. self.assertQuerysetEqual(self.r.article_set.filter(headline__startswith='This'), ["<Article: This is a test>"])
  149. self.assertEqual(self.r.article_set.count(), 2)
  150. self.assertEqual(self.r2.article_set.count(), 1)
  151. # Get articles by id
  152. self.assertQuerysetEqual(Article.objects.filter(id__exact=self.a.id), ["<Article: This is a test>"])
  153. self.assertQuerysetEqual(Article.objects.filter(pk=self.a.id), ["<Article: This is a test>"])
  154. # Query on an article property
  155. self.assertQuerysetEqual(Article.objects.filter(headline__startswith='This'), ["<Article: This is a test>"])
  156. # The API automatically follows relationships as far as you need.
  157. # Use double underscores to separate relationships.
  158. # This works as many levels deep as you want. There's no limit.
  159. # Find all Articles for any Reporter whose first name is "John".
  160. self.assertQuerysetEqual(
  161. Article.objects.filter(reporter__first_name__exact='John'),
  162. ["<Article: John's second story>", "<Article: This is a test>"]
  163. )
  164. # Check that implied __exact also works
  165. self.assertQuerysetEqual(
  166. Article.objects.filter(reporter__first_name='John'),
  167. ["<Article: John's second story>", "<Article: This is a test>"]
  168. )
  169. # Query twice over the related field.
  170. self.assertQuerysetEqual(
  171. Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact='Smith'),
  172. ["<Article: John's second story>", "<Article: This is a test>"]
  173. )
  174. # The underlying query only makes one join when a related table is referenced twice.
  175. queryset = Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact='Smith')
  176. self.assertNumQueries(1, list, queryset)
  177. self.assertEqual(queryset.query.get_compiler(queryset.db).as_sql()[0].count('INNER JOIN'), 1)
  178. # The automatically joined table has a predictable name.
  179. self.assertQuerysetEqual(
  180. Article.objects.filter(reporter__first_name__exact='John').extra(
  181. where=["many_to_one_reporter.last_name='Smith'"]),
  182. ["<Article: John's second story>", "<Article: This is a test>"]
  183. )
  184. # ... and should work fine with the unicode that comes out of forms.Form.cleaned_data
  185. self.assertQuerysetEqual(
  186. (Article.objects
  187. .filter(reporter__first_name__exact='John')
  188. .extra(where=["many_to_one_reporter.last_name='%s'" % 'Smith'])),
  189. ["<Article: John's second story>", "<Article: This is a test>"]
  190. )
  191. # Find all Articles for a Reporter.
  192. # Use direct ID check, pk check, and object comparison
  193. self.assertQuerysetEqual(
  194. Article.objects.filter(reporter__id__exact=self.r.id),
  195. [
  196. "<Article: John's second story>",
  197. "<Article: This is a test>",
  198. ])
  199. self.assertQuerysetEqual(
  200. Article.objects.filter(reporter__pk=self.r.id),
  201. [
  202. "<Article: John's second story>",
  203. "<Article: This is a test>",
  204. ])
  205. self.assertQuerysetEqual(
  206. Article.objects.filter(reporter=self.r.id),
  207. [
  208. "<Article: John's second story>",
  209. "<Article: This is a test>",
  210. ])
  211. self.assertQuerysetEqual(
  212. Article.objects.filter(reporter=self.r),
  213. [
  214. "<Article: John's second story>",
  215. "<Article: This is a test>",
  216. ])
  217. self.assertQuerysetEqual(
  218. Article.objects.filter(reporter__in=[self.r.id, self.r2.id]).distinct(),
  219. [
  220. "<Article: John's second story>",
  221. "<Article: Paul's story>",
  222. "<Article: This is a test>",
  223. ])
  224. self.assertQuerysetEqual(
  225. Article.objects.filter(reporter__in=[self.r, self.r2]).distinct(),
  226. [
  227. "<Article: John's second story>",
  228. "<Article: Paul's story>",
  229. "<Article: This is a test>",
  230. ])
  231. # You can also use a queryset instead of a literal list of instances.
  232. # The queryset must be reduced to a list of values using values(),
  233. # then converted into a query
  234. self.assertQuerysetEqual(
  235. Article.objects.filter(
  236. reporter__in=Reporter.objects.filter(first_name='John').values('pk').query
  237. ).distinct(),
  238. [
  239. "<Article: John's second story>",
  240. "<Article: This is a test>",
  241. ])
  242. def test_reverse_selects(self):
  243. a3 = Article.objects.create(
  244. headline="Third article",
  245. pub_date=datetime.date(2005, 7, 27),
  246. reporter_id=self.r.id,
  247. )
  248. Article.objects.create(
  249. headline="Fourth article",
  250. pub_date=datetime.date(2005, 7, 27),
  251. reporter_id=self.r.id,
  252. )
  253. john_smith = ["<Reporter: John Smith>"]
  254. # Reporters can be queried
  255. self.assertQuerysetEqual(Reporter.objects.filter(id__exact=self.r.id), john_smith)
  256. self.assertQuerysetEqual(Reporter.objects.filter(pk=self.r.id), john_smith)
  257. self.assertQuerysetEqual(Reporter.objects.filter(first_name__startswith='John'), john_smith)
  258. # Reporters can query in opposite direction of ForeignKey definition
  259. self.assertQuerysetEqual(Reporter.objects.filter(article__id__exact=self.a.id), john_smith)
  260. self.assertQuerysetEqual(Reporter.objects.filter(article__pk=self.a.id), john_smith)
  261. self.assertQuerysetEqual(Reporter.objects.filter(article=self.a.id), john_smith)
  262. self.assertQuerysetEqual(Reporter.objects.filter(article=self.a), john_smith)
  263. self.assertQuerysetEqual(Reporter.objects.filter(article__in=[self.a.id, a3.id]).distinct(), john_smith)
  264. self.assertQuerysetEqual(Reporter.objects.filter(article__in=[self.a.id, a3]).distinct(), john_smith)
  265. self.assertQuerysetEqual(Reporter.objects.filter(article__in=[self.a, a3]).distinct(), john_smith)
  266. self.assertQuerysetEqual(
  267. Reporter.objects.filter(article__headline__startswith='T'),
  268. ["<Reporter: John Smith>", "<Reporter: John Smith>"],
  269. ordered=False
  270. )
  271. self.assertQuerysetEqual(Reporter.objects.filter(article__headline__startswith='T').distinct(), john_smith)
  272. # Counting in the opposite direction works in conjunction with distinct()
  273. self.assertEqual(Reporter.objects.filter(article__headline__startswith='T').count(), 2)
  274. self.assertEqual(Reporter.objects.filter(article__headline__startswith='T').distinct().count(), 1)
  275. # Queries can go round in circles.
  276. self.assertQuerysetEqual(
  277. Reporter.objects.filter(article__reporter__first_name__startswith='John'),
  278. [
  279. "<Reporter: John Smith>",
  280. "<Reporter: John Smith>",
  281. "<Reporter: John Smith>",
  282. ],
  283. ordered=False
  284. )
  285. self.assertQuerysetEqual(
  286. Reporter.objects.filter(article__reporter__first_name__startswith='John').distinct(),
  287. john_smith
  288. )
  289. self.assertQuerysetEqual(Reporter.objects.filter(article__reporter__exact=self.r).distinct(), john_smith)
  290. # Check that implied __exact also works.
  291. self.assertQuerysetEqual(Reporter.objects.filter(article__reporter=self.r).distinct(), john_smith)
  292. # It's possible to use values() calls across many-to-one relations.
  293. # (Note, too, that we clear the ordering here so as not to drag the
  294. # 'headline' field into the columns being used to determine uniqueness)
  295. d = {'reporter__first_name': 'John', 'reporter__last_name': 'Smith'}
  296. qs = Article.objects.filter(
  297. reporter=self.r,
  298. ).distinct().order_by().values('reporter__first_name', 'reporter__last_name')
  299. self.assertEqual([d], list(qs))
  300. def test_select_related(self):
  301. # Check that Article.objects.select_related().dates() works properly when
  302. # there are multiple Articles with the same date but different foreign-key
  303. # objects (Reporters).
  304. r1 = Reporter.objects.create(first_name='Mike', last_name='Royko', email='royko@suntimes.com')
  305. r2 = Reporter.objects.create(first_name='John', last_name='Kass', email='jkass@tribune.com')
  306. Article.objects.create(headline='First', pub_date=datetime.date(1980, 4, 23), reporter=r1)
  307. Article.objects.create(headline='Second', pub_date=datetime.date(1980, 4, 23), reporter=r2)
  308. self.assertEqual(
  309. list(Article.objects.select_related().dates('pub_date', 'day')),
  310. [datetime.date(1980, 4, 23), datetime.date(2005, 7, 27)]
  311. )
  312. self.assertEqual(
  313. list(Article.objects.select_related().dates('pub_date', 'month')),
  314. [datetime.date(1980, 4, 1), datetime.date(2005, 7, 1)]
  315. )
  316. self.assertEqual(
  317. list(Article.objects.select_related().dates('pub_date', 'year')),
  318. [datetime.date(1980, 1, 1), datetime.date(2005, 1, 1)]
  319. )
  320. def test_delete(self):
  321. self.r.article_set.create(headline="John's second story", pub_date=datetime.date(2005, 7, 29))
  322. self.r2.article_set.create(headline="Paul's story", pub_date=datetime.date(2006, 1, 17))
  323. Article.objects.create(headline="Third article", pub_date=datetime.date(2005, 7, 27), reporter_id=self.r.id)
  324. Article.objects.create(
  325. headline="Fourth article",
  326. pub_date=datetime.date(2005, 7, 27),
  327. reporter_id=str(self.r.id),
  328. )
  329. # If you delete a reporter, his articles will be deleted.
  330. self.assertQuerysetEqual(
  331. Article.objects.all(),
  332. [
  333. "<Article: Fourth article>",
  334. "<Article: John's second story>",
  335. "<Article: Paul's story>",
  336. "<Article: Third article>",
  337. "<Article: This is a test>",
  338. ]
  339. )
  340. self.assertQuerysetEqual(
  341. Reporter.objects.order_by('first_name'),
  342. ["<Reporter: John Smith>", "<Reporter: Paul Jones>"]
  343. )
  344. self.r2.delete()
  345. self.assertQuerysetEqual(
  346. Article.objects.all(),
  347. [
  348. "<Article: Fourth article>",
  349. "<Article: John's second story>",
  350. "<Article: Third article>",
  351. "<Article: This is a test>",
  352. ]
  353. )
  354. self.assertQuerysetEqual(Reporter.objects.order_by('first_name'), ["<Reporter: John Smith>"])
  355. # You can delete using a JOIN in the query.
  356. Reporter.objects.filter(article__headline__startswith='This').delete()
  357. self.assertQuerysetEqual(Reporter.objects.all(), [])
  358. self.assertQuerysetEqual(Article.objects.all(), [])
  359. def test_explicit_fk(self):
  360. # Create a new Article with get_or_create using an explicit value
  361. # for a ForeignKey.
  362. a2, created = Article.objects.get_or_create(
  363. headline="John's second test",
  364. pub_date=datetime.date(2011, 5, 7),
  365. reporter_id=self.r.id,
  366. )
  367. self.assertTrue(created)
  368. self.assertEqual(a2.reporter.id, self.r.id)
  369. # You can specify filters containing the explicit FK value.
  370. self.assertQuerysetEqual(
  371. Article.objects.filter(reporter_id__exact=self.r.id),
  372. ["<Article: John's second test>", "<Article: This is a test>"]
  373. )
  374. # Create an Article by Paul for the same date.
  375. a3 = Article.objects.create(
  376. headline="Paul's commentary",
  377. pub_date=datetime.date(2011, 5, 7),
  378. reporter_id=self.r2.id,
  379. )
  380. self.assertEqual(a3.reporter.id, self.r2.id)
  381. # Get should respect explicit foreign keys as well.
  382. with self.assertRaises(MultipleObjectsReturned):
  383. Article.objects.get(reporter_id=self.r.id)
  384. self.assertEqual(
  385. repr(a3),
  386. repr(Article.objects.get(reporter_id=self.r2.id, pub_date=datetime.date(2011, 5, 7)))
  387. )
  388. def test_deepcopy_and_circular_references(self):
  389. # Regression for #12876 -- Model methods that include queries that
  390. # recursive don't cause recursion depth problems under deepcopy.
  391. self.r.cached_query = Article.objects.filter(reporter=self.r)
  392. self.assertEqual(repr(deepcopy(self.r)), "<Reporter: John Smith>")
  393. def test_manager_class_caching(self):
  394. r1 = Reporter.objects.create(first_name='Mike')
  395. r2 = Reporter.objects.create(first_name='John')
  396. # Same twice
  397. self.assertIs(r1.article_set.__class__, r1.article_set.__class__)
  398. # Same as each other
  399. self.assertIs(r1.article_set.__class__, r2.article_set.__class__)
  400. def test_create_relation_with_ugettext_lazy(self):
  401. reporter = Reporter.objects.create(first_name='John', last_name='Smith', email='john.smith@example.com')
  402. lazy = ugettext_lazy('test')
  403. reporter.article_set.create(headline=lazy, pub_date=datetime.date(2011, 6, 10))
  404. notlazy = six.text_type(lazy)
  405. article = reporter.article_set.get()
  406. self.assertEqual(article.headline, notlazy)
  407. def test_values_list_exception(self):
  408. expected_message = "Cannot resolve keyword 'notafield' into field. Choices are: %s"
  409. reporter_fields = ', '.join(sorted(f.name for f in Reporter._meta.get_fields()))
  410. with self.assertRaisesMessage(FieldError, expected_message % reporter_fields):
  411. Article.objects.values_list('reporter__notafield')
  412. article_fields = ', '.join(['EXTRA'] + sorted(f.name for f in Article._meta.get_fields()))
  413. with self.assertRaisesMessage(FieldError, expected_message % article_fields):
  414. Article.objects.extra(select={'EXTRA': 'EXTRA_SELECT'}).values_list('notafield')
  415. def test_fk_assignment_and_related_object_cache(self):
  416. # Tests of ForeignKey assignment and the related-object cache (see #6886).
  417. p = Parent.objects.create(name="Parent")
  418. c = Child.objects.create(name="Child", parent=p)
  419. # Look up the object again so that we get a "fresh" object.
  420. c = Child.objects.get(name="Child")
  421. p = c.parent
  422. # Accessing the related object again returns the exactly same object.
  423. self.assertIs(c.parent, p)
  424. # But if we kill the cache, we get a new object.
  425. del c._parent_cache
  426. self.assertIsNot(c.parent, p)
  427. # Assigning a new object results in that object getting cached immediately.
  428. p2 = Parent.objects.create(name="Parent 2")
  429. c.parent = p2
  430. self.assertIs(c.parent, p2)
  431. # Assigning None succeeds if field is null=True.
  432. p.bestchild = None
  433. self.assertIsNone(p.bestchild)
  434. # bestchild should still be None after saving.
  435. p.save()
  436. self.assertIsNone(p.bestchild)
  437. # bestchild should still be None after fetching the object again.
  438. p = Parent.objects.get(name="Parent")
  439. self.assertIsNone(p.bestchild)
  440. # Assigning None will not fail: Child.parent is null=False.
  441. setattr(c, "parent", None)
  442. # You also can't assign an object of the wrong type here
  443. with self.assertRaises(ValueError):
  444. setattr(c, "parent", First(id=1, second=1))
  445. # You can assign None to Child.parent during object creation.
  446. Child(name='xyzzy', parent=None)
  447. # But when trying to save a Child with parent=None, the database will
  448. # raise IntegrityError.
  449. with self.assertRaises(IntegrityError), transaction.atomic():
  450. Child.objects.create(name='xyzzy', parent=None)
  451. # Creation using keyword argument should cache the related object.
  452. p = Parent.objects.get(name="Parent")
  453. c = Child(parent=p)
  454. self.assertIs(c.parent, p)
  455. # Creation using keyword argument and unsaved related instance (#8070).
  456. p = Parent()
  457. msg = "save() prohibited to prevent data loss due to unsaved related object 'parent'."
  458. with self.assertRaisesMessage(ValueError, msg):
  459. Child.objects.create(parent=p)
  460. msg = "save() prohibited to prevent data loss due to unsaved related object 'parent'."
  461. with self.assertRaisesMessage(ValueError, msg):
  462. ToFieldChild.objects.create(parent=p)
  463. # Creation using attname keyword argument and an id will cause the
  464. # related object to be fetched.
  465. p = Parent.objects.get(name="Parent")
  466. c = Child(parent_id=p.id)
  467. self.assertIsNot(c.parent, p)
  468. self.assertEqual(c.parent, p)
  469. def test_fk_to_bigautofield(self):
  470. ch = City.objects.create(name='Chicago')
  471. District.objects.create(city=ch, name='Far South')
  472. District.objects.create(city=ch, name='North')
  473. ny = City.objects.create(name='New York', id=2 ** 33)
  474. District.objects.create(city=ny, name='Brooklyn')
  475. District.objects.create(city=ny, name='Manhattan')
  476. def test_multiple_foreignkeys(self):
  477. # Test of multiple ForeignKeys to the same model (bug #7125).
  478. c1 = Category.objects.create(name='First')
  479. c2 = Category.objects.create(name='Second')
  480. c3 = Category.objects.create(name='Third')
  481. r1 = Record.objects.create(category=c1)
  482. r2 = Record.objects.create(category=c1)
  483. r3 = Record.objects.create(category=c2)
  484. r4 = Record.objects.create(category=c2)
  485. r5 = Record.objects.create(category=c3)
  486. Relation.objects.create(left=r1, right=r2)
  487. Relation.objects.create(left=r3, right=r4)
  488. Relation.objects.create(left=r1, right=r3)
  489. Relation.objects.create(left=r5, right=r2)
  490. Relation.objects.create(left=r3, right=r2)
  491. q1 = Relation.objects.filter(left__category__name__in=['First'], right__category__name__in=['Second'])
  492. self.assertQuerysetEqual(q1, ["<Relation: First - Second>"])
  493. q2 = Category.objects.filter(record__left_set__right__category__name='Second').order_by('name')
  494. self.assertQuerysetEqual(q2, ["<Category: First>", "<Category: Second>"])
  495. p = Parent.objects.create(name="Parent")
  496. c = Child.objects.create(name="Child", parent=p)
  497. with self.assertRaises(ValueError):
  498. Child.objects.create(name="Grandchild", parent=c)
  499. def test_fk_instantiation_outside_model(self):
  500. # Regression for #12190 -- Should be able to instantiate a FK outside
  501. # of a model, and interrogate its related field.
  502. cat = models.ForeignKey(Category, models.CASCADE)
  503. self.assertEqual('id', cat.remote_field.get_related_field().name)
  504. def test_relation_unsaved(self):
  505. # Test that the <field>_set manager does not join on Null value fields (#17541)
  506. Third.objects.create(name='Third 1')
  507. Third.objects.create(name='Third 2')
  508. th = Third(name="testing")
  509. # The object isn't saved an thus the relation field is null - we won't even
  510. # execute a query in this case.
  511. with self.assertNumQueries(0):
  512. self.assertEqual(th.child_set.count(), 0)
  513. th.save()
  514. # Now the model is saved, so we will need to execute an query.
  515. with self.assertNumQueries(1):
  516. self.assertEqual(th.child_set.count(), 0)
  517. def test_related_object(self):
  518. public_school = School.objects.create(is_public=True)
  519. public_student = Student.objects.create(school=public_school)
  520. private_school = School.objects.create(is_public=False)
  521. private_student = Student.objects.create(school=private_school)
  522. # Only one school is available via all() due to the custom default manager.
  523. self.assertQuerysetEqual(School.objects.all(), ["<School: School object>"])
  524. self.assertEqual(public_student.school, public_school)
  525. # Make sure the base manager is used so that an student can still access
  526. # its related school even if the default manager doesn't normally
  527. # allow it.
  528. self.assertEqual(private_student.school, private_school)
  529. # If the manager is marked "use_for_related_fields", it'll get used instead
  530. # of the "bare" queryset. Usually you'd define this as a property on the class,
  531. # but this approximates that in a way that's easier in tests.
  532. School._default_manager.use_for_related_fields = True
  533. try:
  534. private_student = Student.objects.get(pk=private_student.pk)
  535. with self.assertRaises(School.DoesNotExist):
  536. private_student.school
  537. finally:
  538. School._default_manager.use_for_related_fields = False
  539. def test_hasattr_related_object(self):
  540. # The exception raised on attribute access when a related object
  541. # doesn't exist should be an instance of a subclass of `AttributeError`
  542. # refs #21563
  543. self.assertFalse(hasattr(Article(), 'reporter'))