tests.py 37 KB

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