tests.py 31 KB

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