tests.py 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. from __future__ import unicode_literals
  2. from datetime import datetime, timedelta
  3. import threading
  4. import warnings
  5. from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
  6. from django.db import connections, DEFAULT_DB_ALIAS
  7. from django.db import DatabaseError
  8. from django.db.models.fields import Field
  9. from django.db.models.fields.related import ForeignObjectRel
  10. from django.db.models.manager import BaseManager
  11. from django.db.models.query import QuerySet, EmptyQuerySet, ValuesListQuerySet, MAX_GET_RESULTS
  12. from django.test import TestCase, TransactionTestCase, skipIfDBFeature, skipUnlessDBFeature
  13. from django.utils import six
  14. from django.utils.translation import ugettext_lazy
  15. from .models import Article, SelfRef, ArticleSelectOnSave
  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='Area man 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. six.assertRaisesRegex(
  61. self,
  62. TypeError,
  63. "'foo' is an invalid keyword argument for this function",
  64. Article,
  65. id=None,
  66. headline='Some headline',
  67. pub_date=datetime(2005, 7, 31),
  68. foo='bar',
  69. )
  70. def test_can_leave_off_value_for_autofield_and_it_gets_value_on_save(self):
  71. """
  72. You can leave off the value for an AutoField when creating an
  73. object, because it'll get filled in automatically when you save().
  74. """
  75. a = Article(headline='Article 5', pub_date=datetime(2005, 7, 31))
  76. a.save()
  77. self.assertEqual(a.headline, 'Article 5')
  78. self.assertNotEqual(a.id, None)
  79. def test_leaving_off_a_field_with_default_set_the_default_will_be_saved(self):
  80. a = Article(pub_date=datetime(2005, 7, 31))
  81. a.save()
  82. self.assertEqual(a.headline, 'Default headline')
  83. def test_for_datetimefields_saves_as_much_precision_as_was_given(self):
  84. """as much precision in *seconds*"""
  85. a1 = Article(
  86. headline='Article 7',
  87. pub_date=datetime(2005, 7, 31, 12, 30),
  88. )
  89. a1.save()
  90. self.assertEqual(Article.objects.get(id__exact=a1.id).pub_date,
  91. datetime(2005, 7, 31, 12, 30))
  92. a2 = Article(
  93. headline='Article 8',
  94. pub_date=datetime(2005, 7, 31, 12, 30, 45),
  95. )
  96. a2.save()
  97. self.assertEqual(Article.objects.get(id__exact=a2.id).pub_date,
  98. datetime(2005, 7, 31, 12, 30, 45))
  99. def test_saving_an_object_again_does_not_create_a_new_object(self):
  100. a = Article(headline='original', pub_date=datetime(2014, 5, 16))
  101. a.save()
  102. current_id = a.id
  103. a.save()
  104. self.assertEqual(a.id, current_id)
  105. a.headline = 'Updated headline'
  106. a.save()
  107. self.assertEqual(a.id, current_id)
  108. def test_querysets_checking_for_membership(self):
  109. headlines = [
  110. 'Area man programs in Python', 'Second article', 'Third article']
  111. some_pub_date = datetime(2014, 5, 16, 12, 1)
  112. for headline in headlines:
  113. Article(headline=headline, pub_date=some_pub_date).save()
  114. a = Article(headline='Some headline', pub_date=some_pub_date)
  115. a.save()
  116. # You can use 'in' to test for membership...
  117. self.assertIn(a, Article.objects.all())
  118. # ... but there will often be more efficient ways if that is all you need:
  119. self.assertTrue(Article.objects.filter(id=a.id).exists())
  120. class ModelTest(TestCase):
  121. def test_objects_attribute_is_only_available_on_the_class_itself(self):
  122. six.assertRaisesRegex(
  123. self,
  124. AttributeError,
  125. "Manager isn't accessible via Article instances",
  126. getattr,
  127. Article(),
  128. "objects",
  129. )
  130. self.assertFalse(hasattr(Article(), 'objects'))
  131. self.assertTrue(hasattr(Article, 'objects'))
  132. def test_queryset_delete_removes_all_items_in_that_queryset(self):
  133. headlines = [
  134. 'An article', 'Article One', 'Amazing article', 'Boring article']
  135. some_pub_date = datetime(2014, 5, 16, 12, 1)
  136. for headline in headlines:
  137. Article(headline=headline, pub_date=some_pub_date).save()
  138. self.assertQuerysetEqual(Article.objects.all().order_by('headline'),
  139. ["<Article: Amazing article>",
  140. "<Article: An article>",
  141. "<Article: Article One>",
  142. "<Article: Boring article>"])
  143. Article.objects.filter(headline__startswith='A').delete()
  144. self.assertQuerysetEqual(Article.objects.all().order_by('headline'),
  145. ["<Article: Boring article>"])
  146. def test_not_equal_and_equal_operators_behave_as_expected_on_instances(self):
  147. some_pub_date = datetime(2014, 5, 16, 12, 1)
  148. a1 = Article.objects.create(headline='First', pub_date=some_pub_date)
  149. a2 = Article.objects.create(headline='Second', pub_date=some_pub_date)
  150. self.assertNotEqual(a1, a2)
  151. self.assertEqual(a1, Article.objects.get(id__exact=a1.id))
  152. self.assertNotEqual(Article.objects.get(id__exact=a1.id), Article.objects.get(id__exact=a2.id))
  153. def test_multiple_objects_max_num_fetched(self):
  154. """
  155. #6785 - get() should fetch a limited number of results.
  156. """
  157. Article.objects.bulk_create(
  158. Article(headline='Area %s' % i, pub_date=datetime(2005, 7, 28))
  159. for i in range(MAX_GET_RESULTS)
  160. )
  161. six.assertRaisesRegex(
  162. self,
  163. MultipleObjectsReturned,
  164. "get\(\) returned more than one Article -- it returned %d!" % MAX_GET_RESULTS,
  165. Article.objects.get,
  166. headline__startswith='Area',
  167. )
  168. Article.objects.create(headline='Area %s' % MAX_GET_RESULTS, pub_date=datetime(2005, 7, 28))
  169. six.assertRaisesRegex(
  170. self,
  171. MultipleObjectsReturned,
  172. "get\(\) returned more than one Article -- it returned more than %d!" % MAX_GET_RESULTS,
  173. Article.objects.get,
  174. headline__startswith='Area',
  175. )
  176. @skipUnlessDBFeature('supports_microsecond_precision')
  177. def test_microsecond_precision(self):
  178. # In PostgreSQL, microsecond-level precision is available.
  179. a9 = Article(
  180. headline='Article 9',
  181. pub_date=datetime(2005, 7, 31, 12, 30, 45, 180),
  182. )
  183. a9.save()
  184. self.assertEqual(Article.objects.get(pk=a9.pk).pub_date,
  185. datetime(2005, 7, 31, 12, 30, 45, 180))
  186. @skipIfDBFeature('supports_microsecond_precision')
  187. def test_microsecond_precision_not_supported(self):
  188. # In MySQL, microsecond-level precision isn't available. You'll lose
  189. # microsecond-level precision once the data is saved.
  190. a9 = Article(
  191. headline='Article 9',
  192. pub_date=datetime(2005, 7, 31, 12, 30, 45, 180),
  193. )
  194. a9.save()
  195. self.assertEqual(Article.objects.get(id__exact=a9.id).pub_date,
  196. datetime(2005, 7, 31, 12, 30, 45))
  197. def test_manually_specify_primary_key(self):
  198. # You can manually specify the primary key when creating a new object.
  199. a101 = Article(
  200. id=101,
  201. headline='Article 101',
  202. pub_date=datetime(2005, 7, 31, 12, 30, 45),
  203. )
  204. a101.save()
  205. a101 = Article.objects.get(pk=101)
  206. self.assertEqual(a101.headline, 'Article 101')
  207. def test_create_method(self):
  208. # You can create saved objects in a single step
  209. a10 = Article.objects.create(
  210. headline="Article 10",
  211. pub_date=datetime(2005, 7, 31, 12, 30, 45),
  212. )
  213. self.assertEqual(Article.objects.get(headline="Article 10"), a10)
  214. def test_year_lookup_edge_case(self):
  215. # Edge-case test: A year lookup should retrieve all objects in
  216. # the given year, including Jan. 1 and Dec. 31.
  217. Article.objects.create(
  218. headline='Article 11',
  219. pub_date=datetime(2008, 1, 1),
  220. )
  221. Article.objects.create(
  222. headline='Article 12',
  223. pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999),
  224. )
  225. self.assertQuerysetEqual(Article.objects.filter(pub_date__year=2008),
  226. ["<Article: Article 11>", "<Article: Article 12>"])
  227. def test_unicode_data(self):
  228. # Unicode data works, too.
  229. a = Article(
  230. headline='\u6797\u539f \u3081\u3050\u307f',
  231. pub_date=datetime(2005, 7, 28),
  232. )
  233. a.save()
  234. self.assertEqual(Article.objects.get(pk=a.id).headline,
  235. '\u6797\u539f \u3081\u3050\u307f')
  236. def test_hash_function(self):
  237. # Model instances have a hash function, so they can be used in sets
  238. # or as dictionary keys. Two models compare as equal if their primary
  239. # keys are equal.
  240. a10 = Article.objects.create(
  241. headline="Article 10",
  242. pub_date=datetime(2005, 7, 31, 12, 30, 45),
  243. )
  244. a11 = Article.objects.create(
  245. headline='Article 11',
  246. pub_date=datetime(2008, 1, 1),
  247. )
  248. a12 = Article.objects.create(
  249. headline='Article 12',
  250. pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999),
  251. )
  252. s = {a10, a11, a12}
  253. self.assertIn(Article.objects.get(headline='Article 11'), s)
  254. def test_field_ordering(self):
  255. """
  256. Field instances have a `__lt__` comparison function to define an
  257. ordering based on their creation. Prior to #17851 this ordering
  258. comparison relied on the now unsupported `__cmp__` and was assuming
  259. compared objects were both Field instances raising `AttributeError`
  260. when it should have returned `NotImplemented`.
  261. """
  262. f1 = Field()
  263. f2 = Field(auto_created=True)
  264. f3 = Field()
  265. self.assertLess(f2, f1)
  266. self.assertGreater(f3, f1)
  267. self.assertIsNotNone(f1)
  268. self.assertNotIn(f2, (None, 1, ''))
  269. def test_extra_method_select_argument_with_dashes_and_values(self):
  270. # The 'select' argument to extra() supports names with dashes in
  271. # them, as long as you use values().
  272. Article.objects.create(
  273. headline="Article 10",
  274. pub_date=datetime(2005, 7, 31, 12, 30, 45),
  275. )
  276. Article.objects.create(
  277. headline='Article 11',
  278. pub_date=datetime(2008, 1, 1),
  279. )
  280. Article.objects.create(
  281. headline='Article 12',
  282. pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999),
  283. )
  284. dicts = Article.objects.filter(
  285. pub_date__year=2008).extra(
  286. select={'dashed-value': '1'}).values('headline', 'dashed-value')
  287. self.assertEqual([sorted(d.items()) for d in dicts],
  288. [[('dashed-value', 1), ('headline', 'Article 11')], [('dashed-value', 1), ('headline', 'Article 12')]])
  289. def test_extra_method_select_argument_with_dashes(self):
  290. # If you use 'select' with extra() and names containing dashes on a
  291. # query that's *not* a values() query, those extra 'select' values
  292. # will silently be ignored.
  293. Article.objects.create(
  294. headline="Article 10",
  295. pub_date=datetime(2005, 7, 31, 12, 30, 45),
  296. )
  297. Article.objects.create(
  298. headline='Article 11',
  299. pub_date=datetime(2008, 1, 1),
  300. )
  301. Article.objects.create(
  302. headline='Article 12',
  303. pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999),
  304. )
  305. articles = Article.objects.filter(
  306. pub_date__year=2008).extra(select={'dashed-value': '1', 'undashedvalue': '2'})
  307. self.assertEqual(articles[0].undashedvalue, 2)
  308. def test_create_relation_with_ugettext_lazy(self):
  309. """
  310. Test that ugettext_lazy objects work when saving model instances
  311. through various methods. Refs #10498.
  312. """
  313. notlazy = 'test'
  314. lazy = ugettext_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 objecs
  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. # Can't be instantiated
  333. with self.assertRaises(TypeError):
  334. EmptyQuerySet()
  335. self.assertIsInstance(Article.objects.none(), EmptyQuerySet)
  336. def test_emptyqs_values(self):
  337. # test for #15959
  338. Article.objects.create(headline='foo', pub_date=datetime.now())
  339. with self.assertNumQueries(0):
  340. qs = Article.objects.none().values_list('pk')
  341. self.assertIsInstance(qs, EmptyQuerySet)
  342. self.assertIsInstance(qs, ValuesListQuerySet)
  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(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(len(Article.objects.none().values_list('id').order_by('id')), 0)
  362. with self.assertNumQueries(0):
  363. self.assertEqual(len(Article.objects.none().filter(
  364. id__in=Article.objects.values_list('id', flat=True))), 0)
  365. @skipUnlessDBFeature('can_distinct_on_fields')
  366. def test_emptyqs_distinct(self):
  367. # Tests for #19426
  368. Article.objects.create(headline='foo', pub_date=datetime.now())
  369. with self.assertNumQueries(0):
  370. self.assertEqual(len(Article.objects.none().distinct('headline', 'pub_date')), 0)
  371. def test_ticket_20278(self):
  372. sr = SelfRef.objects.create()
  373. with self.assertRaises(ObjectDoesNotExist):
  374. SelfRef.objects.get(selfref=sr)
  375. def test_eq(self):
  376. self.assertEqual(Article(id=1), Article(id=1))
  377. self.assertNotEqual(Article(id=1), object())
  378. self.assertNotEqual(object(), Article(id=1))
  379. a = Article()
  380. self.assertEqual(a, a)
  381. self.assertNotEqual(Article(), a)
  382. def test_hash(self):
  383. # Value based on PK
  384. self.assertEqual(hash(Article(id=1)), hash(1))
  385. with self.assertRaises(TypeError):
  386. # No PK value -> unhashable (because save() would then change
  387. # hash)
  388. hash(Article())
  389. class ModelLookupTest(TestCase):
  390. def setUp(self):
  391. # Create an Article.
  392. self.a = Article(
  393. id=None,
  394. headline='Area woman programs in Python',
  395. pub_date=datetime(2005, 7, 28),
  396. )
  397. # Save it into the database. You have to call save() explicitly.
  398. self.a.save()
  399. def test_all_lookup(self):
  400. # Change values by changing the attributes, then calling save().
  401. self.a.headline = 'Area man programs in Python'
  402. self.a.save()
  403. # Article.objects.all() returns all the articles in the database.
  404. self.assertQuerysetEqual(Article.objects.all(),
  405. ['<Article: Area man programs in Python>'])
  406. def test_rich_lookup(self):
  407. # Django provides a rich database lookup API.
  408. self.assertEqual(Article.objects.get(id__exact=self.a.id), self.a)
  409. self.assertEqual(Article.objects.get(headline__startswith='Area woman'), self.a)
  410. self.assertEqual(Article.objects.get(pub_date__year=2005), self.a)
  411. self.assertEqual(Article.objects.get(pub_date__year=2005, pub_date__month=7), self.a)
  412. self.assertEqual(Article.objects.get(pub_date__year=2005, pub_date__month=7, pub_date__day=28), self.a)
  413. self.assertEqual(Article.objects.get(pub_date__week_day=5), self.a)
  414. def test_equal_lookup(self):
  415. # The "__exact" lookup type can be omitted, as a shortcut.
  416. self.assertEqual(Article.objects.get(id=self.a.id), self.a)
  417. self.assertEqual(Article.objects.get(headline='Area woman programs in Python'), self.a)
  418. self.assertQuerysetEqual(
  419. Article.objects.filter(pub_date__year=2005),
  420. ['<Article: Area woman programs in Python>'],
  421. )
  422. self.assertQuerysetEqual(
  423. Article.objects.filter(pub_date__year=2004),
  424. [],
  425. )
  426. self.assertQuerysetEqual(
  427. Article.objects.filter(pub_date__year=2005, pub_date__month=7),
  428. ['<Article: Area woman programs in Python>'],
  429. )
  430. self.assertQuerysetEqual(
  431. Article.objects.filter(pub_date__week_day=5),
  432. ['<Article: Area woman programs in Python>'],
  433. )
  434. self.assertQuerysetEqual(
  435. Article.objects.filter(pub_date__week_day=6),
  436. [],
  437. )
  438. def test_does_not_exist(self):
  439. # Django raises an Article.DoesNotExist exception for get() if the
  440. # parameters don't match any object.
  441. six.assertRaisesRegex(
  442. self,
  443. ObjectDoesNotExist,
  444. "Article matching query does not exist.",
  445. Article.objects.get,
  446. id__exact=2000,
  447. )
  448. # To avoid dict-ordering related errors check only one lookup
  449. # in single assert.
  450. self.assertRaises(
  451. ObjectDoesNotExist,
  452. Article.objects.get,
  453. pub_date__year=2005,
  454. pub_date__month=8,
  455. )
  456. six.assertRaisesRegex(
  457. self,
  458. ObjectDoesNotExist,
  459. "Article matching query does not exist.",
  460. Article.objects.get,
  461. pub_date__week_day=6,
  462. )
  463. def test_lookup_by_primary_key(self):
  464. # Lookup by a primary key is the most common case, so Django
  465. # provides a shortcut for primary-key exact lookups.
  466. # The following is identical to articles.get(id=a.id).
  467. self.assertEqual(Article.objects.get(pk=self.a.id), self.a)
  468. # pk can be used as a shortcut for the primary key name in any query.
  469. self.assertQuerysetEqual(Article.objects.filter(pk__in=[self.a.id]),
  470. ["<Article: Area woman programs in Python>"])
  471. # Model instances of the same type and same ID are considered equal.
  472. a = Article.objects.get(pk=self.a.id)
  473. b = Article.objects.get(pk=self.a.id)
  474. self.assertEqual(a, b)
  475. def test_too_many(self):
  476. # Create a very similar object
  477. a = Article(
  478. id=None,
  479. headline='Area man programs in Python',
  480. pub_date=datetime(2005, 7, 28),
  481. )
  482. a.save()
  483. self.assertEqual(Article.objects.count(), 2)
  484. # Django raises an Article.MultipleObjectsReturned exception if the
  485. # lookup matches more than one object
  486. six.assertRaisesRegex(
  487. self,
  488. MultipleObjectsReturned,
  489. "get\(\) returned more than one Article -- it returned 2!",
  490. Article.objects.get,
  491. headline__startswith='Area',
  492. )
  493. six.assertRaisesRegex(
  494. self,
  495. MultipleObjectsReturned,
  496. "get\(\) returned more than one Article -- it returned 2!",
  497. Article.objects.get,
  498. pub_date__year=2005,
  499. )
  500. six.assertRaisesRegex(
  501. self,
  502. MultipleObjectsReturned,
  503. "get\(\) returned more than one Article -- it returned 2!",
  504. Article.objects.get,
  505. pub_date__year=2005,
  506. pub_date__month=7,
  507. )
  508. class ConcurrentSaveTests(TransactionTestCase):
  509. available_apps = ['basic']
  510. @skipUnlessDBFeature('test_db_allows_multiple_connections')
  511. def test_concurrent_delete_with_save(self):
  512. """
  513. Test fetching, deleting and finally saving an object - we should get
  514. an insert in this case.
  515. """
  516. a = Article.objects.create(headline='foo', pub_date=datetime.now())
  517. exceptions = []
  518. def deleter():
  519. try:
  520. # Do not delete a directly - doing so alters its state.
  521. Article.objects.filter(pk=a.pk).delete()
  522. except Exception as e:
  523. exceptions.append(e)
  524. finally:
  525. connections[DEFAULT_DB_ALIAS].close()
  526. self.assertEqual(len(exceptions), 0)
  527. t = threading.Thread(target=deleter)
  528. t.start()
  529. t.join()
  530. a.save()
  531. self.assertEqual(Article.objects.get(pk=a.pk).headline, 'foo')
  532. class ManagerTest(TestCase):
  533. QUERYSET_PROXY_METHODS = [
  534. 'none',
  535. 'count',
  536. 'dates',
  537. 'datetimes',
  538. 'distinct',
  539. 'extra',
  540. 'get',
  541. 'get_or_create',
  542. 'update_or_create',
  543. 'create',
  544. 'bulk_create',
  545. 'filter',
  546. 'aggregate',
  547. 'annotate',
  548. 'complex_filter',
  549. 'exclude',
  550. 'in_bulk',
  551. 'iterator',
  552. 'earliest',
  553. 'latest',
  554. 'first',
  555. 'last',
  556. 'order_by',
  557. 'select_for_update',
  558. 'select_related',
  559. 'prefetch_related',
  560. 'values',
  561. 'values_list',
  562. 'update',
  563. 'reverse',
  564. 'defer',
  565. 'only',
  566. 'using',
  567. 'exists',
  568. '_insert',
  569. '_update',
  570. 'raw',
  571. ]
  572. def test_manager_methods(self):
  573. """
  574. This test ensures that the correct set of methods from `QuerySet`
  575. are copied onto `Manager`.
  576. It's particularly useful to prevent accidentally leaking new methods
  577. into `Manager`. New `QuerySet` methods that should also be copied onto
  578. `Manager` will need to be added to `ManagerTest.QUERYSET_PROXY_METHODS`.
  579. """
  580. self.assertEqual(
  581. sorted(BaseManager._get_queryset_methods(QuerySet).keys()),
  582. sorted(self.QUERYSET_PROXY_METHODS),
  583. )
  584. class SelectOnSaveTests(TestCase):
  585. def test_select_on_save(self):
  586. a1 = Article.objects.create(pub_date=datetime.now())
  587. with self.assertNumQueries(1):
  588. a1.save()
  589. asos = ArticleSelectOnSave.objects.create(pub_date=datetime.now())
  590. with self.assertNumQueries(2):
  591. asos.save()
  592. with self.assertNumQueries(1):
  593. asos.save(force_update=True)
  594. Article.objects.all().delete()
  595. with self.assertRaises(DatabaseError):
  596. with self.assertNumQueries(1):
  597. asos.save(force_update=True)
  598. def test_select_on_save_lying_update(self):
  599. """
  600. Test that select_on_save works correctly if the database
  601. doesn't return correct information about matched rows from
  602. UPDATE.
  603. """
  604. # Change the manager to not return "row matched" for update().
  605. # We are going to change the Article's _base_manager class
  606. # dynamically. This is a bit of a hack, but it seems hard to
  607. # test this properly otherwise. Article's manager, because
  608. # proxy models use their parent model's _base_manager.
  609. orig_class = Article._base_manager.__class__
  610. class FakeQuerySet(QuerySet):
  611. # Make sure the _update method below is in fact called.
  612. called = False
  613. def _update(self, *args, **kwargs):
  614. FakeQuerySet.called = True
  615. super(FakeQuerySet, self)._update(*args, **kwargs)
  616. return 0
  617. class FakeManager(orig_class):
  618. def get_queryset(self):
  619. return FakeQuerySet(self.model)
  620. try:
  621. Article._base_manager.__class__ = FakeManager
  622. asos = ArticleSelectOnSave.objects.create(pub_date=datetime.now())
  623. with self.assertNumQueries(3):
  624. asos.save()
  625. self.assertTrue(FakeQuerySet.called)
  626. # This is not wanted behavior, but this is how Django has always
  627. # behaved for databases that do not return correct information
  628. # about matched rows for UPDATE.
  629. with self.assertRaises(DatabaseError):
  630. asos.save(force_update=True)
  631. with self.assertRaises(DatabaseError):
  632. asos.save(update_fields=['pub_date'])
  633. finally:
  634. Article._base_manager.__class__ = orig_class
  635. class ModelRefreshTests(TestCase):
  636. def _truncate_ms(self, val):
  637. # MySQL < 5.6.4 removes microseconds from the datetimes which can cause
  638. # problems when comparing the original value to that loaded from DB
  639. return val - timedelta(microseconds=val.microsecond)
  640. def test_refresh(self):
  641. a = Article.objects.create(pub_date=self._truncate_ms(datetime.now()))
  642. Article.objects.create(pub_date=self._truncate_ms(datetime.now()))
  643. Article.objects.filter(pk=a.pk).update(headline='new headline')
  644. with self.assertNumQueries(1):
  645. a.refresh_from_db()
  646. self.assertEqual(a.headline, 'new headline')
  647. orig_pub_date = a.pub_date
  648. new_pub_date = a.pub_date + timedelta(10)
  649. Article.objects.update(headline='new headline 2', pub_date=new_pub_date)
  650. with self.assertNumQueries(1):
  651. a.refresh_from_db(fields=['headline'])
  652. self.assertEqual(a.headline, 'new headline 2')
  653. self.assertEqual(a.pub_date, orig_pub_date)
  654. with self.assertNumQueries(1):
  655. a.refresh_from_db()
  656. self.assertEqual(a.pub_date, new_pub_date)
  657. def test_refresh_fk(self):
  658. s1 = SelfRef.objects.create()
  659. s2 = SelfRef.objects.create()
  660. s3 = SelfRef.objects.create(selfref=s1)
  661. s3_copy = SelfRef.objects.get(pk=s3.pk)
  662. s3_copy.selfref.touched = True
  663. s3.selfref = s2
  664. s3.save()
  665. with self.assertNumQueries(1):
  666. s3_copy.refresh_from_db()
  667. with self.assertNumQueries(1):
  668. # The old related instance was thrown away (the selfref_id has
  669. # changed). It needs to be reloaded on access, so one query
  670. # executed.
  671. self.assertFalse(hasattr(s3_copy.selfref, 'touched'))
  672. self.assertEqual(s3_copy.selfref, s2)
  673. def test_refresh_unsaved(self):
  674. pub_date = self._truncate_ms(datetime.now())
  675. a = Article.objects.create(pub_date=pub_date)
  676. a2 = Article(id=a.pk)
  677. with self.assertNumQueries(1):
  678. a2.refresh_from_db()
  679. self.assertEqual(a2.pub_date, pub_date)
  680. self.assertEqual(a2._state.db, "default")
  681. def test_refresh_no_fields(self):
  682. a = Article.objects.create(pub_date=self._truncate_ms(datetime.now()))
  683. with self.assertNumQueries(0):
  684. a.refresh_from_db(fields=[])
  685. class TestRelatedObjectDeprecation(TestCase):
  686. def test_field_related_deprecation(self):
  687. field = SelfRef._meta.get_field('selfref')
  688. with warnings.catch_warnings(record=True) as warns:
  689. warnings.simplefilter('always')
  690. self.assertIsInstance(field.related, ForeignObjectRel)
  691. self.assertEqual(len(warns), 1)
  692. self.assertEqual(
  693. str(warns.pop().message),
  694. 'Usage of field.related has been deprecated. Use field.rel instead.'
  695. )