PageRenderTime 53ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/modeltests/basic/tests.py

https://code.google.com/p/mango-py/
Python | 554 lines | 407 code | 74 blank | 73 comment | 10 complexity | ab9b8e9cf6d858c58028501b1f8bab6d MD5 | raw file
Possible License(s): BSD-3-Clause
  1. from datetime import datetime
  2. from django.core.exceptions import ObjectDoesNotExist
  3. from django.db import models, DEFAULT_DB_ALIAS, connection
  4. from django.db.models.fields import FieldDoesNotExist
  5. from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
  6. from models import Article
  7. class ModelTest(TestCase):
  8. def test_lookup(self):
  9. # No articles are in the system yet.
  10. self.assertQuerysetEqual(Article.objects.all(), [])
  11. # Create an Article.
  12. a = Article(
  13. id=None,
  14. headline='Area man programs in Python',
  15. pub_date=datetime(2005, 7, 28),
  16. )
  17. # Save it into the database. You have to call save() explicitly.
  18. a.save()
  19. # Now it has an ID.
  20. self.assertTrue(a.id != None)
  21. # Models have a pk property that is an alias for the primary key
  22. # attribute (by default, the 'id' attribute).
  23. self.assertEqual(a.pk, a.id)
  24. # Access database columns via Python attributes.
  25. self.assertEqual(a.headline, 'Area man programs in Python')
  26. self.assertEqual(a.pub_date, datetime(2005, 7, 28, 0, 0))
  27. # Change values by changing the attributes, then calling save().
  28. a.headline = 'Area woman programs in Python'
  29. a.save()
  30. # Article.objects.all() returns all the articles in the database.
  31. self.assertQuerysetEqual(Article.objects.all(),
  32. ['<Article: Area woman programs in Python>'])
  33. # Django provides a rich database lookup API.
  34. self.assertEqual(Article.objects.get(id__exact=a.id), a)
  35. self.assertEqual(Article.objects.get(headline__startswith='Area woman'), a)
  36. self.assertEqual(Article.objects.get(pub_date__year=2005), a)
  37. self.assertEqual(Article.objects.get(pub_date__year=2005, pub_date__month=7), a)
  38. self.assertEqual(Article.objects.get(pub_date__year=2005, pub_date__month=7, pub_date__day=28), a)
  39. self.assertEqual(Article.objects.get(pub_date__week_day=5), a)
  40. # The "__exact" lookup type can be omitted, as a shortcut.
  41. self.assertEqual(Article.objects.get(id=a.id), a)
  42. self.assertEqual(Article.objects.get(headline='Area woman programs in Python'), a)
  43. self.assertQuerysetEqual(
  44. Article.objects.filter(pub_date__year=2005),
  45. ['<Article: Area woman programs in Python>'],
  46. )
  47. self.assertQuerysetEqual(
  48. Article.objects.filter(pub_date__year=2004),
  49. [],
  50. )
  51. self.assertQuerysetEqual(
  52. Article.objects.filter(pub_date__year=2005, pub_date__month=7),
  53. ['<Article: Area woman programs in Python>'],
  54. )
  55. self.assertQuerysetEqual(
  56. Article.objects.filter(pub_date__week_day=5),
  57. ['<Article: Area woman programs in Python>'],
  58. )
  59. self.assertQuerysetEqual(
  60. Article.objects.filter(pub_date__week_day=6),
  61. [],
  62. )
  63. # Django raises an Article.DoesNotExist exception for get() if the
  64. # parameters don't match any object.
  65. self.assertRaisesRegexp(
  66. ObjectDoesNotExist,
  67. "Article matching query does not exist.",
  68. Article.objects.get,
  69. id__exact=2000,
  70. )
  71. self.assertRaisesRegexp(
  72. ObjectDoesNotExist,
  73. "Article matching query does not exist.",
  74. Article.objects.get,
  75. pub_date__year=2005,
  76. pub_date__month=8,
  77. )
  78. self.assertRaisesRegexp(
  79. ObjectDoesNotExist,
  80. "Article matching query does not exist.",
  81. Article.objects.get,
  82. pub_date__week_day=6,
  83. )
  84. # Lookup by a primary key is the most common case, so Django
  85. # provides a shortcut for primary-key exact lookups.
  86. # The following is identical to articles.get(id=a.id).
  87. self.assertEqual(Article.objects.get(pk=a.id), a)
  88. # pk can be used as a shortcut for the primary key name in any query.
  89. self.assertQuerysetEqual(Article.objects.filter(pk__in=[a.id]),
  90. ["<Article: Area woman programs in Python>"])
  91. # Model instances of the same type and same ID are considered equal.
  92. a = Article.objects.get(pk=a.id)
  93. b = Article.objects.get(pk=a.id)
  94. self.assertEqual(a, b)
  95. def test_object_creation(self):
  96. # Create an Article.
  97. a = Article(
  98. id=None,
  99. headline='Area man programs in Python',
  100. pub_date=datetime(2005, 7, 28),
  101. )
  102. # Save it into the database. You have to call save() explicitly.
  103. a.save()
  104. # You can initialize a model instance using positional arguments,
  105. # which should match the field order as defined in the model.
  106. a2 = Article(None, 'Second article', datetime(2005, 7, 29))
  107. a2.save()
  108. self.assertNotEqual(a2.id, a.id)
  109. self.assertEqual(a2.headline, 'Second article')
  110. self.assertEqual(a2.pub_date, datetime(2005, 7, 29, 0, 0))
  111. # ...or, you can use keyword arguments.
  112. a3 = Article(
  113. id=None,
  114. headline='Third article',
  115. pub_date=datetime(2005, 7, 30),
  116. )
  117. a3.save()
  118. self.assertNotEqual(a3.id, a.id)
  119. self.assertNotEqual(a3.id, a2.id)
  120. self.assertEqual(a3.headline, 'Third article')
  121. self.assertEqual(a3.pub_date, datetime(2005, 7, 30, 0, 0))
  122. # You can also mix and match position and keyword arguments, but
  123. # be sure not to duplicate field information.
  124. a4 = Article(None, 'Fourth article', pub_date=datetime(2005, 7, 31))
  125. a4.save()
  126. self.assertEqual(a4.headline, 'Fourth article')
  127. # Don't use invalid keyword arguments.
  128. self.assertRaisesRegexp(
  129. TypeError,
  130. "'foo' is an invalid keyword argument for this function",
  131. Article,
  132. id=None,
  133. headline='Invalid',
  134. pub_date=datetime(2005, 7, 31),
  135. foo='bar',
  136. )
  137. # You can leave off the value for an AutoField when creating an
  138. # object, because it'll get filled in automatically when you save().
  139. a5 = Article(headline='Article 6', pub_date=datetime(2005, 7, 31))
  140. a5.save()
  141. self.assertEqual(a5.headline, 'Article 6')
  142. # If you leave off a field with "default" set, Django will use
  143. # the default.
  144. a6 = Article(pub_date=datetime(2005, 7, 31))
  145. a6.save()
  146. self.assertEqual(a6.headline, u'Default headline')
  147. # For DateTimeFields, Django saves as much precision (in seconds)
  148. # as you give it.
  149. a7 = Article(
  150. headline='Article 7',
  151. pub_date=datetime(2005, 7, 31, 12, 30),
  152. )
  153. a7.save()
  154. self.assertEqual(Article.objects.get(id__exact=a7.id).pub_date,
  155. datetime(2005, 7, 31, 12, 30))
  156. a8 = Article(
  157. headline='Article 8',
  158. pub_date=datetime(2005, 7, 31, 12, 30, 45),
  159. )
  160. a8.save()
  161. self.assertEqual(Article.objects.get(id__exact=a8.id).pub_date,
  162. datetime(2005, 7, 31, 12, 30, 45))
  163. # Saving an object again doesn't create a new object -- it just saves
  164. # the old one.
  165. current_id = a8.id
  166. a8.save()
  167. self.assertEqual(a8.id, current_id)
  168. a8.headline = 'Updated article 8'
  169. a8.save()
  170. self.assertEqual(a8.id, current_id)
  171. # Check that != and == operators behave as expecte on instances
  172. self.assertTrue(a7 != a8)
  173. self.assertFalse(a7 == a8)
  174. self.assertEqual(a8, Article.objects.get(id__exact=a8.id))
  175. self.assertTrue(Article.objects.get(id__exact=a8.id) != Article.objects.get(id__exact=a7.id))
  176. self.assertFalse(Article.objects.get(id__exact=a8.id) == Article.objects.get(id__exact=a7.id))
  177. # You can use 'in' to test for membership...
  178. self.assertTrue(a8 in Article.objects.all())
  179. # ... but there will often be more efficient ways if that is all you need:
  180. self.assertTrue(Article.objects.filter(id=a8.id).exists())
  181. # dates() returns a list of available dates of the given scope for
  182. # the given field.
  183. self.assertQuerysetEqual(
  184. Article.objects.dates('pub_date', 'year'),
  185. ["datetime.datetime(2005, 1, 1, 0, 0)"])
  186. self.assertQuerysetEqual(
  187. Article.objects.dates('pub_date', 'month'),
  188. ["datetime.datetime(2005, 7, 1, 0, 0)"])
  189. self.assertQuerysetEqual(
  190. Article.objects.dates('pub_date', 'day'),
  191. ["datetime.datetime(2005, 7, 28, 0, 0)",
  192. "datetime.datetime(2005, 7, 29, 0, 0)",
  193. "datetime.datetime(2005, 7, 30, 0, 0)",
  194. "datetime.datetime(2005, 7, 31, 0, 0)"])
  195. self.assertQuerysetEqual(
  196. Article.objects.dates('pub_date', 'day', order='ASC'),
  197. ["datetime.datetime(2005, 7, 28, 0, 0)",
  198. "datetime.datetime(2005, 7, 29, 0, 0)",
  199. "datetime.datetime(2005, 7, 30, 0, 0)",
  200. "datetime.datetime(2005, 7, 31, 0, 0)"])
  201. self.assertQuerysetEqual(
  202. Article.objects.dates('pub_date', 'day', order='DESC'),
  203. ["datetime.datetime(2005, 7, 31, 0, 0)",
  204. "datetime.datetime(2005, 7, 30, 0, 0)",
  205. "datetime.datetime(2005, 7, 29, 0, 0)",
  206. "datetime.datetime(2005, 7, 28, 0, 0)"])
  207. # dates() requires valid arguments.
  208. self.assertRaisesRegexp(
  209. TypeError,
  210. "dates\(\) takes at least 3 arguments \(1 given\)",
  211. Article.objects.dates,
  212. )
  213. self.assertRaisesRegexp(
  214. FieldDoesNotExist,
  215. "Article has no field named 'invalid_field'",
  216. Article.objects.dates,
  217. "invalid_field",
  218. "year",
  219. )
  220. self.assertRaisesRegexp(
  221. AssertionError,
  222. "'kind' must be one of 'year', 'month' or 'day'.",
  223. Article.objects.dates,
  224. "pub_date",
  225. "bad_kind",
  226. )
  227. self.assertRaisesRegexp(
  228. AssertionError,
  229. "'order' must be either 'ASC' or 'DESC'.",
  230. Article.objects.dates,
  231. "pub_date",
  232. "year",
  233. order="bad order",
  234. )
  235. # Use iterator() with dates() to return a generator that lazily
  236. # requests each result one at a time, to save memory.
  237. dates = []
  238. for article in Article.objects.dates('pub_date', 'day', order='DESC').iterator():
  239. dates.append(article)
  240. self.assertEqual(dates, [
  241. datetime(2005, 7, 31, 0, 0),
  242. datetime(2005, 7, 30, 0, 0),
  243. datetime(2005, 7, 29, 0, 0),
  244. datetime(2005, 7, 28, 0, 0)])
  245. # You can combine queries with & and |.
  246. s1 = Article.objects.filter(id__exact=a.id)
  247. s2 = Article.objects.filter(id__exact=a2.id)
  248. self.assertQuerysetEqual(s1 | s2,
  249. ["<Article: Area man programs in Python>",
  250. "<Article: Second article>"])
  251. self.assertQuerysetEqual(s1 & s2, [])
  252. # You can get the number of objects like this:
  253. self.assertEqual(len(Article.objects.filter(id__exact=a.id)), 1)
  254. # You can get items using index and slice notation.
  255. self.assertEqual(Article.objects.all()[0], a)
  256. self.assertQuerysetEqual(Article.objects.all()[1:3],
  257. ["<Article: Second article>", "<Article: Third article>"])
  258. s3 = Article.objects.filter(id__exact=a3.id)
  259. self.assertQuerysetEqual((s1 | s2 | s3)[::2],
  260. ["<Article: Area man programs in Python>",
  261. "<Article: Third article>"])
  262. # Slicing works with longs.
  263. self.assertEqual(Article.objects.all()[0L], a)
  264. self.assertQuerysetEqual(Article.objects.all()[1L:3L],
  265. ["<Article: Second article>", "<Article: Third article>"])
  266. self.assertQuerysetEqual((s1 | s2 | s3)[::2L],
  267. ["<Article: Area man programs in Python>",
  268. "<Article: Third article>"])
  269. # And can be mixed with ints.
  270. self.assertQuerysetEqual(Article.objects.all()[1:3L],
  271. ["<Article: Second article>", "<Article: Third article>"])
  272. # Slices (without step) are lazy:
  273. self.assertQuerysetEqual(Article.objects.all()[0:5].filter(),
  274. ["<Article: Area man programs in Python>",
  275. "<Article: Second article>",
  276. "<Article: Third article>",
  277. "<Article: Article 6>",
  278. "<Article: Default headline>"])
  279. # Slicing again works:
  280. self.assertQuerysetEqual(Article.objects.all()[0:5][0:2],
  281. ["<Article: Area man programs in Python>",
  282. "<Article: Second article>"])
  283. self.assertQuerysetEqual(Article.objects.all()[0:5][:2],
  284. ["<Article: Area man programs in Python>",
  285. "<Article: Second article>"])
  286. self.assertQuerysetEqual(Article.objects.all()[0:5][4:],
  287. ["<Article: Default headline>"])
  288. self.assertQuerysetEqual(Article.objects.all()[0:5][5:], [])
  289. # Some more tests!
  290. self.assertQuerysetEqual(Article.objects.all()[2:][0:2],
  291. ["<Article: Third article>", "<Article: Article 6>"])
  292. self.assertQuerysetEqual(Article.objects.all()[2:][:2],
  293. ["<Article: Third article>", "<Article: Article 6>"])
  294. self.assertQuerysetEqual(Article.objects.all()[2:][2:3],
  295. ["<Article: Default headline>"])
  296. # Using an offset without a limit is also possible.
  297. self.assertQuerysetEqual(Article.objects.all()[5:],
  298. ["<Article: Fourth article>",
  299. "<Article: Article 7>",
  300. "<Article: Updated article 8>"])
  301. # Also, once you have sliced you can't filter, re-order or combine
  302. self.assertRaisesRegexp(
  303. AssertionError,
  304. "Cannot filter a query once a slice has been taken.",
  305. Article.objects.all()[0:5].filter,
  306. id=a.id,
  307. )
  308. self.assertRaisesRegexp(
  309. AssertionError,
  310. "Cannot reorder a query once a slice has been taken.",
  311. Article.objects.all()[0:5].order_by,
  312. 'id',
  313. )
  314. try:
  315. Article.objects.all()[0:1] & Article.objects.all()[4:5]
  316. self.fail('Should raise an AssertionError')
  317. except AssertionError, e:
  318. self.assertEqual(str(e), "Cannot combine queries once a slice has been taken.")
  319. except Exception, e:
  320. self.fail('Should raise an AssertionError, not %s' % e)
  321. # Negative slices are not supported, due to database constraints.
  322. # (hint: inverting your ordering might do what you need).
  323. try:
  324. Article.objects.all()[-1]
  325. self.fail('Should raise an AssertionError')
  326. except AssertionError, e:
  327. self.assertEqual(str(e), "Negative indexing is not supported.")
  328. except Exception, e:
  329. self.fail('Should raise an AssertionError, not %s' % e)
  330. error = None
  331. try:
  332. Article.objects.all()[0:-5]
  333. except Exception, e:
  334. error = e
  335. self.assertTrue(isinstance(error, AssertionError))
  336. self.assertEqual(str(error), "Negative indexing is not supported.")
  337. # An Article instance doesn't have access to the "objects" attribute.
  338. # That's only available on the class.
  339. self.assertRaisesRegexp(
  340. AttributeError,
  341. "Manager isn't accessible via Article instances",
  342. getattr,
  343. a7,
  344. "objects",
  345. )
  346. # Bulk delete test: How many objects before and after the delete?
  347. self.assertQuerysetEqual(Article.objects.all(),
  348. ["<Article: Area man programs in Python>",
  349. "<Article: Second article>",
  350. "<Article: Third article>",
  351. "<Article: Article 6>",
  352. "<Article: Default headline>",
  353. "<Article: Fourth article>",
  354. "<Article: Article 7>",
  355. "<Article: Updated article 8>"])
  356. Article.objects.filter(id__lte=a4.id).delete()
  357. self.assertQuerysetEqual(Article.objects.all(),
  358. ["<Article: Article 6>",
  359. "<Article: Default headline>",
  360. "<Article: Article 7>",
  361. "<Article: Updated article 8>"])
  362. @skipUnlessDBFeature('supports_microsecond_precision')
  363. def test_microsecond_precision(self):
  364. # In PostgreSQL, microsecond-level precision is available.
  365. a9 = Article(
  366. headline='Article 9',
  367. pub_date=datetime(2005, 7, 31, 12, 30, 45, 180),
  368. )
  369. a9.save()
  370. self.assertEqual(Article.objects.get(pk=a9.pk).pub_date,
  371. datetime(2005, 7, 31, 12, 30, 45, 180))
  372. @skipIfDBFeature('supports_microsecond_precision')
  373. def test_microsecond_precision_not_supported(self):
  374. # In MySQL, microsecond-level precision isn't available. You'll lose
  375. # microsecond-level precision once the data is saved.
  376. a9 = Article(
  377. headline='Article 9',
  378. pub_date=datetime(2005, 7, 31, 12, 30, 45, 180),
  379. )
  380. a9.save()
  381. self.assertEqual(Article.objects.get(id__exact=a9.id).pub_date,
  382. datetime(2005, 7, 31, 12, 30, 45))
  383. def test_manually_specify_primary_key(self):
  384. # You can manually specify the primary key when creating a new object.
  385. a101 = Article(
  386. id=101,
  387. headline='Article 101',
  388. pub_date=datetime(2005, 7, 31, 12, 30, 45),
  389. )
  390. a101.save()
  391. a101 = Article.objects.get(pk=101)
  392. self.assertEqual(a101.headline, u'Article 101')
  393. def test_create_method(self):
  394. # You can create saved objects in a single step
  395. a10 = Article.objects.create(
  396. headline="Article 10",
  397. pub_date=datetime(2005, 7, 31, 12, 30, 45),
  398. )
  399. self.assertEqual(Article.objects.get(headline="Article 10"), a10)
  400. def test_year_lookup_edge_case(self):
  401. # Edge-case test: A year lookup should retrieve all objects in
  402. # the given year, including Jan. 1 and Dec. 31.
  403. a11 = Article.objects.create(
  404. headline='Article 11',
  405. pub_date=datetime(2008, 1, 1),
  406. )
  407. a12 = Article.objects.create(
  408. headline='Article 12',
  409. pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999),
  410. )
  411. self.assertQuerysetEqual(Article.objects.filter(pub_date__year=2008),
  412. ["<Article: Article 11>", "<Article: Article 12>"])
  413. def test_unicode_data(self):
  414. # Unicode data works, too.
  415. a = Article(
  416. headline=u'\u6797\u539f \u3081\u3050\u307f',
  417. pub_date=datetime(2005, 7, 28),
  418. )
  419. a.save()
  420. self.assertEqual(Article.objects.get(pk=a.id).headline,
  421. u'\u6797\u539f \u3081\u3050\u307f')
  422. def test_hash_function(self):
  423. # Model instances have a hash function, so they can be used in sets
  424. # or as dictionary keys. Two models compare as equal if their primary
  425. # keys are equal.
  426. a10 = Article.objects.create(
  427. headline="Article 10",
  428. pub_date=datetime(2005, 7, 31, 12, 30, 45),
  429. )
  430. a11 = Article.objects.create(
  431. headline='Article 11',
  432. pub_date=datetime(2008, 1, 1),
  433. )
  434. a12 = Article.objects.create(
  435. headline='Article 12',
  436. pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999),
  437. )
  438. s = set([a10, a11, a12])
  439. self.assertTrue(Article.objects.get(headline='Article 11') in s)
  440. def test_extra_method_select_argument_with_dashes_and_values(self):
  441. # The 'select' argument to extra() supports names with dashes in
  442. # them, as long as you use values().
  443. a10 = Article.objects.create(
  444. headline="Article 10",
  445. pub_date=datetime(2005, 7, 31, 12, 30, 45),
  446. )
  447. a11 = Article.objects.create(
  448. headline='Article 11',
  449. pub_date=datetime(2008, 1, 1),
  450. )
  451. a12 = Article.objects.create(
  452. headline='Article 12',
  453. pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999),
  454. )
  455. dicts = Article.objects.filter(
  456. pub_date__year=2008).extra(
  457. select={'dashed-value': '1'}
  458. ).values('headline', 'dashed-value')
  459. self.assertEqual([sorted(d.items()) for d in dicts],
  460. [[('dashed-value', 1), ('headline', u'Article 11')], [('dashed-value', 1), ('headline', u'Article 12')]])
  461. def test_extra_method_select_argument_with_dashes(self):
  462. # If you use 'select' with extra() and names containing dashes on a
  463. # query that's *not* a values() query, those extra 'select' values
  464. # will silently be ignored.
  465. a10 = Article.objects.create(
  466. headline="Article 10",
  467. pub_date=datetime(2005, 7, 31, 12, 30, 45),
  468. )
  469. a11 = Article.objects.create(
  470. headline='Article 11',
  471. pub_date=datetime(2008, 1, 1),
  472. )
  473. a12 = Article.objects.create(
  474. headline='Article 12',
  475. pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999),
  476. )
  477. articles = Article.objects.filter(
  478. pub_date__year=2008).extra(
  479. select={'dashed-value': '1', 'undashedvalue': '2'})
  480. self.assertEqual(articles[0].undashedvalue, 2)