PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/tests/regressiontests/extra_regress/tests.py

https://code.google.com/p/mango-py/
Python | 314 lines | 273 code | 18 blank | 23 comment | 1 complexity | 501664980e720f32fd38197d6f577880 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. from django.test import TestCase
  2. from django.utils.datastructures import SortedDict
  3. from django.contrib.auth.models import User
  4. from regressiontests.extra_regress.models import TestObject, Order, \
  5. RevisionableModel
  6. import datetime
  7. class ExtraRegressTests(TestCase):
  8. def setUp(self):
  9. self.u = User.objects.create_user(
  10. username="fred",
  11. password="secret",
  12. email="fred@example.com"
  13. )
  14. def test_regression_7314_7372(self):
  15. """
  16. Regression tests for #7314 and #7372
  17. """
  18. rm = RevisionableModel.objects.create(
  19. title='First Revision',
  20. when=datetime.datetime(2008, 9, 28, 10, 30, 0)
  21. )
  22. self.assertEqual(rm.pk, rm.base.pk)
  23. rm2 = rm.new_revision()
  24. rm2.title = "Second Revision"
  25. rm.when = datetime.datetime(2008, 9, 28, 14, 25, 0)
  26. rm2.save()
  27. self.assertEqual(rm2.title, 'Second Revision')
  28. self.assertEqual(rm2.base.title, 'First Revision')
  29. self.assertNotEqual(rm2.pk, rm.pk)
  30. self.assertEqual(rm2.base.pk, rm.pk)
  31. # Queryset to match most recent revision:
  32. qs = RevisionableModel.objects.extra(
  33. where=["%(table)s.id IN (SELECT MAX(rev.id) FROM %(table)s rev GROUP BY rev.base_id)" % {
  34. 'table': RevisionableModel._meta.db_table,
  35. }]
  36. )
  37. self.assertQuerysetEqual(qs,
  38. [('Second Revision', 'First Revision')],
  39. transform=lambda r: (r.title, r.base.title)
  40. )
  41. # Queryset to search for string in title:
  42. qs2 = RevisionableModel.objects.filter(title__contains="Revision")
  43. self.assertQuerysetEqual(qs2,
  44. [
  45. ('First Revision', 'First Revision'),
  46. ('Second Revision', 'First Revision'),
  47. ],
  48. transform=lambda r: (r.title, r.base.title)
  49. )
  50. # Following queryset should return the most recent revision:
  51. self.assertQuerysetEqual(qs & qs2,
  52. [('Second Revision', 'First Revision')],
  53. transform=lambda r: (r.title, r.base.title)
  54. )
  55. def test_extra_stay_tied(self):
  56. # Extra select parameters should stay tied to their corresponding
  57. # select portions. Applies when portions are updated or otherwise
  58. # moved around.
  59. qs = User.objects.extra(
  60. select=SortedDict((("alpha", "%s"), ("beta", "2"), ("gamma", "%s"))),
  61. select_params=(1, 3)
  62. )
  63. qs = qs.extra(select={"beta": 4})
  64. qs = qs.extra(select={"alpha": "%s"}, select_params=[5])
  65. self.assertEqual(
  66. list(qs.filter(id=self.u.id).values('alpha', 'beta', 'gamma')),
  67. [{'alpha': 5, 'beta': 4, 'gamma': 3}]
  68. )
  69. def test_regression_7957(self):
  70. """
  71. Regression test for #7957: Combining extra() calls should leave the
  72. corresponding parameters associated with the right extra() bit. I.e.
  73. internal dictionary must remain sorted.
  74. """
  75. self.assertEqual(
  76. User.objects.extra(select={"alpha": "%s"}, select_params=(1,)
  77. ).extra(select={"beta": "%s"}, select_params=(2,))[0].alpha,
  78. 1)
  79. self.assertEqual(
  80. User.objects.extra(select={"beta": "%s"}, select_params=(1,)
  81. ).extra(select={"alpha": "%s"}, select_params=(2,))[0].alpha,
  82. 2)
  83. def test_regression_7961(self):
  84. """
  85. Regression test for #7961: When not using a portion of an
  86. extra(...) in a query, remove any corresponding parameters from the
  87. query as well.
  88. """
  89. self.assertEqual(
  90. list(User.objects.extra(select={"alpha": "%s"}, select_params=(-6,)
  91. ).filter(id=self.u.id).values_list('id', flat=True)),
  92. [self.u.id]
  93. )
  94. def test_regression_8063(self):
  95. """
  96. Regression test for #8063: limiting a query shouldn't discard any
  97. extra() bits.
  98. """
  99. qs = User.objects.all().extra(where=['id=%s'], params=[self.u.id])
  100. self.assertQuerysetEqual(qs, ['<User: fred>'])
  101. self.assertQuerysetEqual(qs[:1], ['<User: fred>'])
  102. def test_regression_8039(self):
  103. """
  104. Regression test for #8039: Ordering sometimes removed relevant tables
  105. from extra(). This test is the critical case: ordering uses a table,
  106. but then removes the reference because of an optimisation. The table
  107. should still be present because of the extra() call.
  108. """
  109. self.assertQuerysetEqual(
  110. Order.objects.extra(where=["username=%s"],
  111. params=["fred"],
  112. tables=["auth_user"]
  113. ).order_by('created_by'),
  114. []
  115. )
  116. def test_regression_8819(self):
  117. """
  118. Regression test for #8819: Fields in the extra(select=...) list
  119. should be available to extra(order_by=...).
  120. """
  121. self.assertQuerysetEqual(
  122. User.objects.filter(pk=self.u.id).extra(select={'extra_field': 1}).distinct(),
  123. ['<User: fred>']
  124. )
  125. self.assertQuerysetEqual(
  126. User.objects.filter(pk=self.u.id).extra(select={'extra_field': 1}, order_by=['extra_field']),
  127. ['<User: fred>']
  128. )
  129. self.assertQuerysetEqual(
  130. User.objects.filter(pk=self.u.id).extra(select={'extra_field': 1}, order_by=['extra_field']).distinct(),
  131. ['<User: fred>']
  132. )
  133. def test_dates_query(self):
  134. """
  135. When calling the dates() method on a queryset with extra selection
  136. columns, we can (and should) ignore those columns. They don't change
  137. the result and cause incorrect SQL to be produced otherwise.
  138. """
  139. rm = RevisionableModel.objects.create(
  140. title='First Revision',
  141. when=datetime.datetime(2008, 9, 28, 10, 30, 0)
  142. )
  143. self.assertQuerysetEqual(
  144. RevisionableModel.objects.extra(select={"the_answer": 'id'}).dates('when', 'month'),
  145. ['datetime.datetime(2008, 9, 1, 0, 0)']
  146. )
  147. def test_values_with_extra(self):
  148. """
  149. Regression test for #10256... If there is a values() clause, Extra
  150. columns are only returned if they are explicitly mentioned.
  151. """
  152. obj = TestObject(first='first', second='second', third='third')
  153. obj.save()
  154. self.assertEqual(
  155. list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values()),
  156. [{'bar': u'second', 'third': u'third', 'second': u'second', 'whiz': u'third', 'foo': u'first', 'id': obj.pk, 'first': u'first'}]
  157. )
  158. # Extra clauses after an empty values clause are still included
  159. self.assertEqual(
  160. list(TestObject.objects.values().extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third'))))),
  161. [{'bar': u'second', 'third': u'third', 'second': u'second', 'whiz': u'third', 'foo': u'first', 'id': obj.pk, 'first': u'first'}]
  162. )
  163. # Extra columns are ignored if not mentioned in the values() clause
  164. self.assertEqual(
  165. list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values('first', 'second')),
  166. [{'second': u'second', 'first': u'first'}]
  167. )
  168. # Extra columns after a non-empty values() clause are ignored
  169. self.assertEqual(
  170. list(TestObject.objects.values('first', 'second').extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third'))))),
  171. [{'second': u'second', 'first': u'first'}]
  172. )
  173. # Extra columns can be partially returned
  174. self.assertEqual(
  175. list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values('first', 'second', 'foo')),
  176. [{'second': u'second', 'foo': u'first', 'first': u'first'}]
  177. )
  178. # Also works if only extra columns are included
  179. self.assertEqual(
  180. list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values('foo', 'whiz')),
  181. [{'foo': u'first', 'whiz': u'third'}]
  182. )
  183. # Values list works the same way
  184. # All columns are returned for an empty values_list()
  185. self.assertEqual(
  186. list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list()),
  187. [(u'first', u'second', u'third', obj.pk, u'first', u'second', u'third')]
  188. )
  189. # Extra columns after an empty values_list() are still included
  190. self.assertEqual(
  191. list(TestObject.objects.values_list().extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third'))))),
  192. [(u'first', u'second', u'third', obj.pk, u'first', u'second', u'third')]
  193. )
  194. # Extra columns ignored completely if not mentioned in values_list()
  195. self.assertEqual(
  196. list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('first', 'second')),
  197. [(u'first', u'second')]
  198. )
  199. # Extra columns after a non-empty values_list() clause are ignored completely
  200. self.assertEqual(
  201. list(TestObject.objects.values_list('first', 'second').extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third'))))),
  202. [(u'first', u'second')]
  203. )
  204. self.assertEqual(
  205. list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('second', flat=True)),
  206. [u'second']
  207. )
  208. # Only the extra columns specified in the values_list() are returned
  209. self.assertEqual(
  210. list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('first', 'second', 'whiz')),
  211. [(u'first', u'second', u'third')]
  212. )
  213. # ...also works if only extra columns are included
  214. self.assertEqual(
  215. list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('foo','whiz')),
  216. [(u'first', u'third')]
  217. )
  218. self.assertEqual(
  219. list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('whiz', flat=True)),
  220. [u'third']
  221. )
  222. # ... and values are returned in the order they are specified
  223. self.assertEqual(
  224. list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('whiz','foo')),
  225. [(u'third', u'first')]
  226. )
  227. self.assertEqual(
  228. list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('first','id')),
  229. [(u'first', obj.pk)]
  230. )
  231. self.assertEqual(
  232. list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('whiz', 'first', 'bar', 'id')),
  233. [(u'third', u'first', u'second', obj.pk)]
  234. )
  235. def test_regression_10847(self):
  236. """
  237. Regression for #10847: the list of extra columns can always be
  238. accurately evaluated. Using an inner query ensures that as_sql() is
  239. producing correct output without requiring full evaluation and
  240. execution of the inner query.
  241. """
  242. obj = TestObject(first='first', second='second', third='third')
  243. obj.save()
  244. self.assertEqual(
  245. list(TestObject.objects.extra(select={'extra': 1}).values('pk')),
  246. [{'pk': obj.pk}]
  247. )
  248. self.assertQuerysetEqual(
  249. TestObject.objects.filter(
  250. pk__in=TestObject.objects.extra(select={'extra': 1}).values('pk')
  251. ),
  252. ['<TestObject: TestObject: first,second,third>']
  253. )
  254. self.assertEqual(
  255. list(TestObject.objects.values('pk').extra(select={'extra': 1})),
  256. [{'pk': obj.pk}]
  257. )
  258. self.assertQuerysetEqual(
  259. TestObject.objects.filter(
  260. pk__in=TestObject.objects.values('pk').extra(select={'extra': 1})
  261. ),
  262. ['<TestObject: TestObject: first,second,third>']
  263. )
  264. self.assertQuerysetEqual(
  265. TestObject.objects.filter(pk=obj.pk) |
  266. TestObject.objects.extra(where=["id > %s"], params=[obj.pk]),
  267. ['<TestObject: TestObject: first,second,third>']
  268. )