tests.py 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  1. import threading
  2. from datetime import datetime, timedelta
  3. from unittest import mock
  4. from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
  5. from django.db import DEFAULT_DB_ALIAS, DatabaseError, connections, models
  6. from django.db.models.manager import BaseManager
  7. from django.db.models.query import MAX_GET_RESULTS, EmptyQuerySet
  8. from django.test import (
  9. SimpleTestCase,
  10. TestCase,
  11. TransactionTestCase,
  12. skipUnlessDBFeature,
  13. )
  14. from django.utils.translation import gettext_lazy
  15. from .models import (
  16. Article,
  17. ArticleSelectOnSave,
  18. ChildPrimaryKeyWithDefault,
  19. FeaturedArticle,
  20. PrimaryKeyWithDefault,
  21. SelfRef,
  22. )
  23. class ModelInstanceCreationTests(TestCase):
  24. def test_object_is_not_written_to_database_until_save_was_called(self):
  25. a = Article(
  26. id=None,
  27. headline="Parrot programs in Python",
  28. pub_date=datetime(2005, 7, 28),
  29. )
  30. self.assertIsNone(a.id)
  31. self.assertEqual(Article.objects.count(), 0)
  32. # Save it into the database. You have to call save() explicitly.
  33. a.save()
  34. self.assertIsNotNone(a.id)
  35. self.assertEqual(Article.objects.count(), 1)
  36. def test_can_initialize_model_instance_using_positional_arguments(self):
  37. """
  38. You can initialize a model instance using positional arguments,
  39. which should match the field order as defined in the model.
  40. """
  41. a = Article(None, "Second article", datetime(2005, 7, 29))
  42. a.save()
  43. self.assertEqual(a.headline, "Second article")
  44. self.assertEqual(a.pub_date, datetime(2005, 7, 29, 0, 0))
  45. def test_can_create_instance_using_kwargs(self):
  46. a = Article(
  47. id=None,
  48. headline="Third article",
  49. pub_date=datetime(2005, 7, 30),
  50. )
  51. a.save()
  52. self.assertEqual(a.headline, "Third article")
  53. self.assertEqual(a.pub_date, datetime(2005, 7, 30, 0, 0))
  54. def test_autofields_generate_different_values_for_each_instance(self):
  55. a1 = Article.objects.create(
  56. headline="First", pub_date=datetime(2005, 7, 30, 0, 0)
  57. )
  58. a2 = Article.objects.create(
  59. headline="First", pub_date=datetime(2005, 7, 30, 0, 0)
  60. )
  61. a3 = Article.objects.create(
  62. headline="First", pub_date=datetime(2005, 7, 30, 0, 0)
  63. )
  64. self.assertNotEqual(a3.id, a1.id)
  65. self.assertNotEqual(a3.id, a2.id)
  66. def test_can_mix_and_match_position_and_kwargs(self):
  67. # You can also mix and match position and keyword arguments, but
  68. # be sure not to duplicate field information.
  69. a = Article(None, "Fourth article", pub_date=datetime(2005, 7, 31))
  70. a.save()
  71. self.assertEqual(a.headline, "Fourth article")
  72. def test_positional_and_keyword_args_for_the_same_field(self):
  73. msg = "Article() got both positional and keyword arguments for field '%s'."
  74. with self.assertRaisesMessage(TypeError, msg % "headline"):
  75. Article(None, "Fifth article", headline="Other headline.")
  76. with self.assertRaisesMessage(TypeError, msg % "headline"):
  77. Article(None, "Sixth article", headline="")
  78. with self.assertRaisesMessage(TypeError, msg % "pub_date"):
  79. Article(None, "Seventh article", datetime(2021, 3, 1), pub_date=None)
  80. def test_cannot_create_instance_with_invalid_kwargs(self):
  81. msg = "Article() got unexpected keyword arguments: 'foo'"
  82. with self.assertRaisesMessage(TypeError, msg):
  83. Article(
  84. id=None,
  85. headline="Some headline",
  86. pub_date=datetime(2005, 7, 31),
  87. foo="bar",
  88. )
  89. msg = "Article() got unexpected keyword arguments: 'foo', 'bar'"
  90. with self.assertRaisesMessage(TypeError, msg):
  91. Article(
  92. id=None,
  93. headline="Some headline",
  94. pub_date=datetime(2005, 7, 31),
  95. foo="bar",
  96. bar="baz",
  97. )
  98. def test_can_leave_off_value_for_autofield_and_it_gets_value_on_save(self):
  99. """
  100. You can leave off the value for an AutoField when creating an
  101. object, because it'll get filled in automatically when you save().
  102. """
  103. a = Article(headline="Article 5", pub_date=datetime(2005, 7, 31))
  104. a.save()
  105. self.assertEqual(a.headline, "Article 5")
  106. self.assertIsNotNone(a.id)
  107. def test_leaving_off_a_field_with_default_set_the_default_will_be_saved(self):
  108. a = Article(pub_date=datetime(2005, 7, 31))
  109. a.save()
  110. self.assertEqual(a.headline, "Default headline")
  111. def test_for_datetimefields_saves_as_much_precision_as_was_given(self):
  112. """as much precision in *seconds*"""
  113. a1 = Article(
  114. headline="Article 7",
  115. pub_date=datetime(2005, 7, 31, 12, 30),
  116. )
  117. a1.save()
  118. self.assertEqual(
  119. Article.objects.get(id__exact=a1.id).pub_date, datetime(2005, 7, 31, 12, 30)
  120. )
  121. a2 = Article(
  122. headline="Article 8",
  123. pub_date=datetime(2005, 7, 31, 12, 30, 45),
  124. )
  125. a2.save()
  126. self.assertEqual(
  127. Article.objects.get(id__exact=a2.id).pub_date,
  128. datetime(2005, 7, 31, 12, 30, 45),
  129. )
  130. def test_saving_an_object_again_does_not_create_a_new_object(self):
  131. a = Article(headline="original", pub_date=datetime(2014, 5, 16))
  132. a.save()
  133. current_id = a.id
  134. a.save()
  135. self.assertEqual(a.id, current_id)
  136. a.headline = "Updated headline"
  137. a.save()
  138. self.assertEqual(a.id, current_id)
  139. def test_querysets_checking_for_membership(self):
  140. headlines = ["Parrot programs in Python", "Second article", "Third article"]
  141. some_pub_date = datetime(2014, 5, 16, 12, 1)
  142. for headline in headlines:
  143. Article(headline=headline, pub_date=some_pub_date).save()
  144. a = Article(headline="Some headline", pub_date=some_pub_date)
  145. a.save()
  146. # You can use 'in' to test for membership...
  147. self.assertIn(a, Article.objects.all())
  148. # ... but there will often be more efficient ways if that is all you need:
  149. self.assertTrue(Article.objects.filter(id=a.id).exists())
  150. def test_save_primary_with_default(self):
  151. # An UPDATE attempt is skipped when a primary key has default.
  152. with self.assertNumQueries(1):
  153. PrimaryKeyWithDefault().save()
  154. def test_save_parent_primary_with_default(self):
  155. # An UPDATE attempt is skipped when an inherited primary key has
  156. # default.
  157. with self.assertNumQueries(2):
  158. ChildPrimaryKeyWithDefault().save()
  159. class ModelTest(TestCase):
  160. def test_objects_attribute_is_only_available_on_the_class_itself(self):
  161. with self.assertRaisesMessage(
  162. AttributeError, "Manager isn't accessible via Article instances"
  163. ):
  164. getattr(
  165. Article(),
  166. "objects",
  167. )
  168. self.assertFalse(hasattr(Article(), "objects"))
  169. self.assertTrue(hasattr(Article, "objects"))
  170. def test_queryset_delete_removes_all_items_in_that_queryset(self):
  171. headlines = ["An article", "Article One", "Amazing article", "Boring article"]
  172. some_pub_date = datetime(2014, 5, 16, 12, 1)
  173. for headline in headlines:
  174. Article(headline=headline, pub_date=some_pub_date).save()
  175. self.assertQuerysetEqual(
  176. Article.objects.order_by("headline"),
  177. sorted(headlines),
  178. transform=lambda a: a.headline,
  179. )
  180. Article.objects.filter(headline__startswith="A").delete()
  181. self.assertEqual(Article.objects.get().headline, "Boring article")
  182. def test_not_equal_and_equal_operators_behave_as_expected_on_instances(self):
  183. some_pub_date = datetime(2014, 5, 16, 12, 1)
  184. a1 = Article.objects.create(headline="First", pub_date=some_pub_date)
  185. a2 = Article.objects.create(headline="Second", pub_date=some_pub_date)
  186. self.assertNotEqual(a1, a2)
  187. self.assertEqual(a1, Article.objects.get(id__exact=a1.id))
  188. self.assertNotEqual(
  189. Article.objects.get(id__exact=a1.id), Article.objects.get(id__exact=a2.id)
  190. )
  191. def test_microsecond_precision(self):
  192. a9 = Article(
  193. headline="Article 9",
  194. pub_date=datetime(2005, 7, 31, 12, 30, 45, 180),
  195. )
  196. a9.save()
  197. self.assertEqual(
  198. Article.objects.get(pk=a9.pk).pub_date,
  199. datetime(2005, 7, 31, 12, 30, 45, 180),
  200. )
  201. def test_manually_specify_primary_key(self):
  202. # You can manually specify the primary key when creating a new object.
  203. a101 = Article(
  204. id=101,
  205. headline="Article 101",
  206. pub_date=datetime(2005, 7, 31, 12, 30, 45),
  207. )
  208. a101.save()
  209. a101 = Article.objects.get(pk=101)
  210. self.assertEqual(a101.headline, "Article 101")
  211. def test_create_method(self):
  212. # You can create saved objects in a single step
  213. a10 = Article.objects.create(
  214. headline="Article 10",
  215. pub_date=datetime(2005, 7, 31, 12, 30, 45),
  216. )
  217. self.assertEqual(Article.objects.get(headline="Article 10"), a10)
  218. def test_year_lookup_edge_case(self):
  219. # Edge-case test: A year lookup should retrieve all objects in
  220. # the given year, including Jan. 1 and Dec. 31.
  221. a11 = Article.objects.create(
  222. headline="Article 11",
  223. pub_date=datetime(2008, 1, 1),
  224. )
  225. a12 = Article.objects.create(
  226. headline="Article 12",
  227. pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999),
  228. )
  229. self.assertSequenceEqual(
  230. Article.objects.filter(pub_date__year=2008),
  231. [a11, a12],
  232. )
  233. def test_unicode_data(self):
  234. # Unicode data works, too.
  235. a = Article(
  236. headline="\u6797\u539f \u3081\u3050\u307f",
  237. pub_date=datetime(2005, 7, 28),
  238. )
  239. a.save()
  240. self.assertEqual(
  241. Article.objects.get(pk=a.id).headline, "\u6797\u539f \u3081\u3050\u307f"
  242. )
  243. def test_hash_function(self):
  244. # Model instances have a hash function, so they can be used in sets
  245. # or as dictionary keys. Two models compare as equal if their primary
  246. # keys are equal.
  247. a10 = Article.objects.create(
  248. headline="Article 10",
  249. pub_date=datetime(2005, 7, 31, 12, 30, 45),
  250. )
  251. a11 = Article.objects.create(
  252. headline="Article 11",
  253. pub_date=datetime(2008, 1, 1),
  254. )
  255. a12 = Article.objects.create(
  256. headline="Article 12",
  257. pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999),
  258. )
  259. s = {a10, a11, a12}
  260. self.assertIn(Article.objects.get(headline="Article 11"), s)
  261. def test_extra_method_select_argument_with_dashes_and_values(self):
  262. # The 'select' argument to extra() supports names with dashes in
  263. # them, as long as you use values().
  264. Article.objects.bulk_create(
  265. [
  266. Article(
  267. headline="Article 10", pub_date=datetime(2005, 7, 31, 12, 30, 45)
  268. ),
  269. Article(headline="Article 11", pub_date=datetime(2008, 1, 1)),
  270. Article(
  271. headline="Article 12",
  272. pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999),
  273. ),
  274. ]
  275. )
  276. dicts = (
  277. Article.objects.filter(pub_date__year=2008)
  278. .extra(select={"dashed-value": "1"})
  279. .values("headline", "dashed-value")
  280. )
  281. self.assertEqual(
  282. [sorted(d.items()) for d in dicts],
  283. [
  284. [("dashed-value", 1), ("headline", "Article 11")],
  285. [("dashed-value", 1), ("headline", "Article 12")],
  286. ],
  287. )
  288. def test_extra_method_select_argument_with_dashes(self):
  289. # If you use 'select' with extra() and names containing dashes on a
  290. # query that's *not* a values() query, those extra 'select' values
  291. # will silently be ignored.
  292. Article.objects.bulk_create(
  293. [
  294. Article(
  295. headline="Article 10", pub_date=datetime(2005, 7, 31, 12, 30, 45)
  296. ),
  297. Article(headline="Article 11", pub_date=datetime(2008, 1, 1)),
  298. Article(
  299. headline="Article 12",
  300. pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999),
  301. ),
  302. ]
  303. )
  304. articles = Article.objects.filter(pub_date__year=2008).extra(
  305. select={"dashed-value": "1", "undashedvalue": "2"}
  306. )
  307. self.assertEqual(articles[0].undashedvalue, 2)
  308. def test_create_relation_with_gettext_lazy(self):
  309. """
  310. gettext_lazy objects work when saving model instances
  311. through various methods. Refs #10498.
  312. """
  313. notlazy = "test"
  314. lazy = gettext_lazy(notlazy)
  315. Article.objects.create(headline=lazy, pub_date=datetime.now())
  316. article = Article.objects.get()
  317. self.assertEqual(article.headline, notlazy)
  318. # test that assign + save works with Promise objects
  319. article.headline = lazy
  320. article.save()
  321. self.assertEqual(article.headline, notlazy)
  322. # test .update()
  323. Article.objects.update(headline=lazy)
  324. article = Article.objects.get()
  325. self.assertEqual(article.headline, notlazy)
  326. # still test bulk_create()
  327. Article.objects.all().delete()
  328. Article.objects.bulk_create([Article(headline=lazy, pub_date=datetime.now())])
  329. article = Article.objects.get()
  330. self.assertEqual(article.headline, notlazy)
  331. def test_emptyqs(self):
  332. msg = "EmptyQuerySet can't be instantiated"
  333. with self.assertRaisesMessage(TypeError, msg):
  334. EmptyQuerySet()
  335. self.assertIsInstance(Article.objects.none(), EmptyQuerySet)
  336. self.assertNotIsInstance("", EmptyQuerySet)
  337. def test_emptyqs_values(self):
  338. # test for #15959
  339. Article.objects.create(headline="foo", pub_date=datetime.now())
  340. with self.assertNumQueries(0):
  341. qs = Article.objects.none().values_list("pk")
  342. self.assertIsInstance(qs, EmptyQuerySet)
  343. self.assertEqual(len(qs), 0)
  344. def test_emptyqs_customqs(self):
  345. # A hacky test for custom QuerySet subclass - refs #17271
  346. Article.objects.create(headline="foo", pub_date=datetime.now())
  347. class CustomQuerySet(models.QuerySet):
  348. def do_something(self):
  349. return "did something"
  350. qs = Article.objects.all()
  351. qs.__class__ = CustomQuerySet
  352. qs = qs.none()
  353. with self.assertNumQueries(0):
  354. self.assertEqual(len(qs), 0)
  355. self.assertIsInstance(qs, EmptyQuerySet)
  356. self.assertEqual(qs.do_something(), "did something")
  357. def test_emptyqs_values_order(self):
  358. # Tests for ticket #17712
  359. Article.objects.create(headline="foo", pub_date=datetime.now())
  360. with self.assertNumQueries(0):
  361. self.assertEqual(
  362. len(Article.objects.none().values_list("id").order_by("id")), 0
  363. )
  364. with self.assertNumQueries(0):
  365. self.assertEqual(
  366. len(
  367. Article.objects.none().filter(
  368. id__in=Article.objects.values_list("id", flat=True)
  369. )
  370. ),
  371. 0,
  372. )
  373. @skipUnlessDBFeature("can_distinct_on_fields")
  374. def test_emptyqs_distinct(self):
  375. # Tests for #19426
  376. Article.objects.create(headline="foo", pub_date=datetime.now())
  377. with self.assertNumQueries(0):
  378. self.assertEqual(
  379. len(Article.objects.none().distinct("headline", "pub_date")), 0
  380. )
  381. def test_ticket_20278(self):
  382. sr = SelfRef.objects.create()
  383. with self.assertRaises(ObjectDoesNotExist):
  384. SelfRef.objects.get(selfref=sr)
  385. def test_eq(self):
  386. self.assertEqual(Article(id=1), Article(id=1))
  387. self.assertNotEqual(Article(id=1), object())
  388. self.assertNotEqual(object(), Article(id=1))
  389. a = Article()
  390. self.assertEqual(a, a)
  391. self.assertEqual(a, mock.ANY)
  392. self.assertNotEqual(Article(), a)
  393. def test_hash(self):
  394. # Value based on PK
  395. self.assertEqual(hash(Article(id=1)), hash(1))
  396. msg = "Model instances without primary key value are unhashable"
  397. with self.assertRaisesMessage(TypeError, msg):
  398. # No PK value -> unhashable (because save() would then change
  399. # hash)
  400. hash(Article())
  401. def test_missing_hash_not_inherited(self):
  402. class NoHash(models.Model):
  403. def __eq__(self, other):
  404. return super.__eq__(other)
  405. with self.assertRaisesMessage(TypeError, "unhashable type: 'NoHash'"):
  406. hash(NoHash(id=1))
  407. def test_specified_parent_hash_inherited(self):
  408. class ParentHash(models.Model):
  409. def __eq__(self, other):
  410. return super.__eq__(other)
  411. __hash__ = models.Model.__hash__
  412. self.assertEqual(hash(ParentHash(id=1)), 1)
  413. def test_delete_and_access_field(self):
  414. # Accessing a field after it's deleted from a model reloads its value.
  415. pub_date = datetime.now()
  416. article = Article.objects.create(headline="foo", pub_date=pub_date)
  417. new_pub_date = article.pub_date + timedelta(days=10)
  418. article.headline = "bar"
  419. article.pub_date = new_pub_date
  420. del article.headline
  421. with self.assertNumQueries(1):
  422. self.assertEqual(article.headline, "foo")
  423. # Fields that weren't deleted aren't reloaded.
  424. self.assertEqual(article.pub_date, new_pub_date)
  425. def test_multiple_objects_max_num_fetched(self):
  426. max_results = MAX_GET_RESULTS - 1
  427. Article.objects.bulk_create(
  428. Article(headline="Area %s" % i, pub_date=datetime(2005, 7, 28))
  429. for i in range(max_results)
  430. )
  431. self.assertRaisesMessage(
  432. MultipleObjectsReturned,
  433. "get() returned more than one Article -- it returned %d!" % max_results,
  434. Article.objects.get,
  435. headline__startswith="Area",
  436. )
  437. Article.objects.create(
  438. headline="Area %s" % max_results, pub_date=datetime(2005, 7, 28)
  439. )
  440. self.assertRaisesMessage(
  441. MultipleObjectsReturned,
  442. "get() returned more than one Article -- it returned more than %d!"
  443. % max_results,
  444. Article.objects.get,
  445. headline__startswith="Area",
  446. )
  447. class ModelLookupTest(TestCase):
  448. @classmethod
  449. def setUpTestData(cls):
  450. # Create an Article.
  451. cls.a = Article(
  452. id=None,
  453. headline="Swallow programs in Python",
  454. pub_date=datetime(2005, 7, 28),
  455. )
  456. # Save it into the database. You have to call save() explicitly.
  457. cls.a.save()
  458. def test_all_lookup(self):
  459. # Change values by changing the attributes, then calling save().
  460. self.a.headline = "Parrot programs in Python"
  461. self.a.save()
  462. # Article.objects.all() returns all the articles in the database.
  463. self.assertSequenceEqual(Article.objects.all(), [self.a])
  464. def test_rich_lookup(self):
  465. # Django provides a rich database lookup API.
  466. self.assertEqual(Article.objects.get(id__exact=self.a.id), self.a)
  467. self.assertEqual(Article.objects.get(headline__startswith="Swallow"), self.a)
  468. self.assertEqual(Article.objects.get(pub_date__year=2005), self.a)
  469. self.assertEqual(
  470. Article.objects.get(pub_date__year=2005, pub_date__month=7), self.a
  471. )
  472. self.assertEqual(
  473. Article.objects.get(
  474. pub_date__year=2005, pub_date__month=7, pub_date__day=28
  475. ),
  476. self.a,
  477. )
  478. self.assertEqual(Article.objects.get(pub_date__week_day=5), self.a)
  479. def test_equal_lookup(self):
  480. # The "__exact" lookup type can be omitted, as a shortcut.
  481. self.assertEqual(Article.objects.get(id=self.a.id), self.a)
  482. self.assertEqual(
  483. Article.objects.get(headline="Swallow programs in Python"), self.a
  484. )
  485. self.assertSequenceEqual(
  486. Article.objects.filter(pub_date__year=2005),
  487. [self.a],
  488. )
  489. self.assertSequenceEqual(
  490. Article.objects.filter(pub_date__year=2004),
  491. [],
  492. )
  493. self.assertSequenceEqual(
  494. Article.objects.filter(pub_date__year=2005, pub_date__month=7),
  495. [self.a],
  496. )
  497. self.assertSequenceEqual(
  498. Article.objects.filter(pub_date__week_day=5),
  499. [self.a],
  500. )
  501. self.assertSequenceEqual(
  502. Article.objects.filter(pub_date__week_day=6),
  503. [],
  504. )
  505. def test_does_not_exist(self):
  506. # Django raises an Article.DoesNotExist exception for get() if the
  507. # parameters don't match any object.
  508. with self.assertRaisesMessage(
  509. ObjectDoesNotExist, "Article matching query does not exist."
  510. ):
  511. Article.objects.get(
  512. id__exact=2000,
  513. )
  514. # To avoid dict-ordering related errors check only one lookup
  515. # in single assert.
  516. with self.assertRaises(ObjectDoesNotExist):
  517. Article.objects.get(pub_date__year=2005, pub_date__month=8)
  518. with self.assertRaisesMessage(
  519. ObjectDoesNotExist, "Article matching query does not exist."
  520. ):
  521. Article.objects.get(
  522. pub_date__week_day=6,
  523. )
  524. def test_lookup_by_primary_key(self):
  525. # Lookup by a primary key is the most common case, so Django
  526. # provides a shortcut for primary-key exact lookups.
  527. # The following is identical to articles.get(id=a.id).
  528. self.assertEqual(Article.objects.get(pk=self.a.id), self.a)
  529. # pk can be used as a shortcut for the primary key name in any query.
  530. self.assertSequenceEqual(Article.objects.filter(pk__in=[self.a.id]), [self.a])
  531. # Model instances of the same type and same ID are considered equal.
  532. a = Article.objects.get(pk=self.a.id)
  533. b = Article.objects.get(pk=self.a.id)
  534. self.assertEqual(a, b)
  535. def test_too_many(self):
  536. # Create a very similar object
  537. a = Article(
  538. id=None,
  539. headline="Swallow bites Python",
  540. pub_date=datetime(2005, 7, 28),
  541. )
  542. a.save()
  543. self.assertEqual(Article.objects.count(), 2)
  544. # Django raises an Article.MultipleObjectsReturned exception if the
  545. # lookup matches more than one object
  546. msg = "get() returned more than one Article -- it returned 2!"
  547. with self.assertRaisesMessage(MultipleObjectsReturned, msg):
  548. Article.objects.get(
  549. headline__startswith="Swallow",
  550. )
  551. with self.assertRaisesMessage(MultipleObjectsReturned, msg):
  552. Article.objects.get(
  553. pub_date__year=2005,
  554. )
  555. with self.assertRaisesMessage(MultipleObjectsReturned, msg):
  556. Article.objects.get(pub_date__year=2005, pub_date__month=7)
  557. class ConcurrentSaveTests(TransactionTestCase):
  558. available_apps = ["basic"]
  559. @skipUnlessDBFeature("test_db_allows_multiple_connections")
  560. def test_concurrent_delete_with_save(self):
  561. """
  562. Test fetching, deleting and finally saving an object - we should get
  563. an insert in this case.
  564. """
  565. a = Article.objects.create(headline="foo", pub_date=datetime.now())
  566. exceptions = []
  567. def deleter():
  568. try:
  569. # Do not delete a directly - doing so alters its state.
  570. Article.objects.filter(pk=a.pk).delete()
  571. except Exception as e:
  572. exceptions.append(e)
  573. finally:
  574. connections[DEFAULT_DB_ALIAS].close()
  575. self.assertEqual(len(exceptions), 0)
  576. t = threading.Thread(target=deleter)
  577. t.start()
  578. t.join()
  579. a.save()
  580. self.assertEqual(Article.objects.get(pk=a.pk).headline, "foo")
  581. class ManagerTest(SimpleTestCase):
  582. QUERYSET_PROXY_METHODS = [
  583. "none",
  584. "count",
  585. "dates",
  586. "datetimes",
  587. "distinct",
  588. "extra",
  589. "get",
  590. "get_or_create",
  591. "update_or_create",
  592. "create",
  593. "bulk_create",
  594. "bulk_update",
  595. "filter",
  596. "aggregate",
  597. "annotate",
  598. "alias",
  599. "complex_filter",
  600. "exclude",
  601. "in_bulk",
  602. "iterator",
  603. "earliest",
  604. "latest",
  605. "first",
  606. "last",
  607. "order_by",
  608. "select_for_update",
  609. "select_related",
  610. "prefetch_related",
  611. "values",
  612. "values_list",
  613. "update",
  614. "reverse",
  615. "defer",
  616. "only",
  617. "using",
  618. "exists",
  619. "contains",
  620. "explain",
  621. "_insert",
  622. "_update",
  623. "raw",
  624. "union",
  625. "intersection",
  626. "difference",
  627. "aaggregate",
  628. "abulk_create",
  629. "abulk_update",
  630. "acontains",
  631. "acount",
  632. "acreate",
  633. "aearliest",
  634. "aexists",
  635. "aexplain",
  636. "afirst",
  637. "aget",
  638. "aget_or_create",
  639. "ain_bulk",
  640. "aiterator",
  641. "alast",
  642. "alatest",
  643. "aupdate",
  644. "aupdate_or_create",
  645. ]
  646. def test_manager_methods(self):
  647. """
  648. This test ensures that the correct set of methods from `QuerySet`
  649. are copied onto `Manager`.
  650. It's particularly useful to prevent accidentally leaking new methods
  651. into `Manager`. New `QuerySet` methods that should also be copied onto
  652. `Manager` will need to be added to `ManagerTest.QUERYSET_PROXY_METHODS`.
  653. """
  654. self.assertEqual(
  655. sorted(BaseManager._get_queryset_methods(models.QuerySet)),
  656. sorted(self.QUERYSET_PROXY_METHODS),
  657. )
  658. class SelectOnSaveTests(TestCase):
  659. def test_select_on_save(self):
  660. a1 = Article.objects.create(pub_date=datetime.now())
  661. with self.assertNumQueries(1):
  662. a1.save()
  663. asos = ArticleSelectOnSave.objects.create(pub_date=datetime.now())
  664. with self.assertNumQueries(2):
  665. asos.save()
  666. with self.assertNumQueries(1):
  667. asos.save(force_update=True)
  668. Article.objects.all().delete()
  669. with self.assertRaisesMessage(
  670. DatabaseError, "Forced update did not affect any rows."
  671. ):
  672. with self.assertNumQueries(1):
  673. asos.save(force_update=True)
  674. def test_select_on_save_lying_update(self):
  675. """
  676. select_on_save works correctly if the database doesn't return correct
  677. information about matched rows from UPDATE.
  678. """
  679. # Change the manager to not return "row matched" for update().
  680. # We are going to change the Article's _base_manager class
  681. # dynamically. This is a bit of a hack, but it seems hard to
  682. # test this properly otherwise. Article's manager, because
  683. # proxy models use their parent model's _base_manager.
  684. orig_class = Article._base_manager._queryset_class
  685. class FakeQuerySet(models.QuerySet):
  686. # Make sure the _update method below is in fact called.
  687. called = False
  688. def _update(self, *args, **kwargs):
  689. FakeQuerySet.called = True
  690. super()._update(*args, **kwargs)
  691. return 0
  692. try:
  693. Article._base_manager._queryset_class = FakeQuerySet
  694. asos = ArticleSelectOnSave.objects.create(pub_date=datetime.now())
  695. with self.assertNumQueries(3):
  696. asos.save()
  697. self.assertTrue(FakeQuerySet.called)
  698. # This is not wanted behavior, but this is how Django has always
  699. # behaved for databases that do not return correct information
  700. # about matched rows for UPDATE.
  701. with self.assertRaisesMessage(
  702. DatabaseError, "Forced update did not affect any rows."
  703. ):
  704. asos.save(force_update=True)
  705. msg = (
  706. "An error occurred in the current transaction. You can't "
  707. "execute queries until the end of the 'atomic' block."
  708. )
  709. with self.assertRaisesMessage(DatabaseError, msg):
  710. asos.save(update_fields=["pub_date"])
  711. finally:
  712. Article._base_manager._queryset_class = orig_class
  713. class ModelRefreshTests(TestCase):
  714. def test_refresh(self):
  715. a = Article.objects.create(pub_date=datetime.now())
  716. Article.objects.create(pub_date=datetime.now())
  717. Article.objects.filter(pk=a.pk).update(headline="new headline")
  718. with self.assertNumQueries(1):
  719. a.refresh_from_db()
  720. self.assertEqual(a.headline, "new headline")
  721. orig_pub_date = a.pub_date
  722. new_pub_date = a.pub_date + timedelta(10)
  723. Article.objects.update(headline="new headline 2", pub_date=new_pub_date)
  724. with self.assertNumQueries(1):
  725. a.refresh_from_db(fields=["headline"])
  726. self.assertEqual(a.headline, "new headline 2")
  727. self.assertEqual(a.pub_date, orig_pub_date)
  728. with self.assertNumQueries(1):
  729. a.refresh_from_db()
  730. self.assertEqual(a.pub_date, new_pub_date)
  731. def test_unknown_kwarg(self):
  732. s = SelfRef.objects.create()
  733. msg = "refresh_from_db() got an unexpected keyword argument 'unknown_kwarg'"
  734. with self.assertRaisesMessage(TypeError, msg):
  735. s.refresh_from_db(unknown_kwarg=10)
  736. def test_lookup_in_fields(self):
  737. s = SelfRef.objects.create()
  738. msg = (
  739. 'Found "__" in fields argument. Relations and transforms are not allowed '
  740. "in fields."
  741. )
  742. with self.assertRaisesMessage(ValueError, msg):
  743. s.refresh_from_db(fields=["foo__bar"])
  744. def test_refresh_fk(self):
  745. s1 = SelfRef.objects.create()
  746. s2 = SelfRef.objects.create()
  747. s3 = SelfRef.objects.create(selfref=s1)
  748. s3_copy = SelfRef.objects.get(pk=s3.pk)
  749. s3_copy.selfref.touched = True
  750. s3.selfref = s2
  751. s3.save()
  752. with self.assertNumQueries(1):
  753. s3_copy.refresh_from_db()
  754. with self.assertNumQueries(1):
  755. # The old related instance was thrown away (the selfref_id has
  756. # changed). It needs to be reloaded on access, so one query
  757. # executed.
  758. self.assertFalse(hasattr(s3_copy.selfref, "touched"))
  759. self.assertEqual(s3_copy.selfref, s2)
  760. def test_refresh_null_fk(self):
  761. s1 = SelfRef.objects.create()
  762. s2 = SelfRef.objects.create(selfref=s1)
  763. s2.selfref = None
  764. s2.refresh_from_db()
  765. self.assertEqual(s2.selfref, s1)
  766. def test_refresh_unsaved(self):
  767. pub_date = datetime.now()
  768. a = Article.objects.create(pub_date=pub_date)
  769. a2 = Article(id=a.pk)
  770. with self.assertNumQueries(1):
  771. a2.refresh_from_db()
  772. self.assertEqual(a2.pub_date, pub_date)
  773. self.assertEqual(a2._state.db, "default")
  774. def test_refresh_fk_on_delete_set_null(self):
  775. a = Article.objects.create(
  776. headline="Parrot programs in Python",
  777. pub_date=datetime(2005, 7, 28),
  778. )
  779. s1 = SelfRef.objects.create(article=a)
  780. a.delete()
  781. s1.refresh_from_db()
  782. self.assertIsNone(s1.article_id)
  783. self.assertIsNone(s1.article)
  784. def test_refresh_no_fields(self):
  785. a = Article.objects.create(pub_date=datetime.now())
  786. with self.assertNumQueries(0):
  787. a.refresh_from_db(fields=[])
  788. def test_refresh_clears_reverse_related(self):
  789. """refresh_from_db() clear cached reverse relations."""
  790. article = Article.objects.create(
  791. headline="Parrot programs in Python",
  792. pub_date=datetime(2005, 7, 28),
  793. )
  794. self.assertFalse(hasattr(article, "featured"))
  795. FeaturedArticle.objects.create(article_id=article.pk)
  796. article.refresh_from_db()
  797. self.assertTrue(hasattr(article, "featured"))
  798. def test_refresh_clears_one_to_one_field(self):
  799. article = Article.objects.create(
  800. headline="Parrot programs in Python",
  801. pub_date=datetime(2005, 7, 28),
  802. )
  803. featured = FeaturedArticle.objects.create(article_id=article.pk)
  804. self.assertEqual(featured.article.headline, "Parrot programs in Python")
  805. article.headline = "Parrot programs in Python 2.0"
  806. article.save()
  807. featured.refresh_from_db()
  808. self.assertEqual(featured.article.headline, "Parrot programs in Python 2.0")
  809. def test_prefetched_cache_cleared(self):
  810. a = Article.objects.create(pub_date=datetime(2005, 7, 28))
  811. s = SelfRef.objects.create(article=a)
  812. # refresh_from_db() without fields=[...]
  813. a1_prefetched = Article.objects.prefetch_related("selfref_set").first()
  814. self.assertCountEqual(a1_prefetched.selfref_set.all(), [s])
  815. s.article = None
  816. s.save()
  817. # Relation is cleared and prefetch cache is stale.
  818. self.assertCountEqual(a1_prefetched.selfref_set.all(), [s])
  819. a1_prefetched.refresh_from_db()
  820. # Cache was cleared and new results are available.
  821. self.assertCountEqual(a1_prefetched.selfref_set.all(), [])
  822. # refresh_from_db() with fields=[...]
  823. a2_prefetched = Article.objects.prefetch_related("selfref_set").first()
  824. self.assertCountEqual(a2_prefetched.selfref_set.all(), [])
  825. s.article = a
  826. s.save()
  827. # Relation is added and prefetch cache is stale.
  828. self.assertCountEqual(a2_prefetched.selfref_set.all(), [])
  829. a2_prefetched.refresh_from_db(fields=["selfref_set"])
  830. # Cache was cleared and new results are available.
  831. self.assertCountEqual(a2_prefetched.selfref_set.all(), [s])