PageRenderTime 1615ms CodeModel.GetById 23ms RepoModel.GetById 3ms app.codeStats 0ms

/tests/modeltests/expressions/tests.py

https://code.google.com/p/mango-py/
Python | 218 lines | 184 code | 18 blank | 16 comment | 0 complexity | a7cbb6148b793378af465e7b870076f0 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. from django.core.exceptions import FieldError
  2. from django.db.models import F
  3. from django.test import TestCase
  4. from models import Company, Employee
  5. class ExpressionsTests(TestCase):
  6. def test_filter(self):
  7. Company.objects.create(
  8. name="Example Inc.", num_employees=2300, num_chairs=5,
  9. ceo=Employee.objects.create(firstname="Joe", lastname="Smith")
  10. )
  11. Company.objects.create(
  12. name="Foobar Ltd.", num_employees=3, num_chairs=4,
  13. ceo=Employee.objects.create(firstname="Frank", lastname="Meyer")
  14. )
  15. Company.objects.create(
  16. name="Test GmbH", num_employees=32, num_chairs=1,
  17. ceo=Employee.objects.create(firstname="Max", lastname="Mustermann")
  18. )
  19. company_query = Company.objects.values(
  20. "name", "num_employees", "num_chairs"
  21. ).order_by(
  22. "name", "num_employees", "num_chairs"
  23. )
  24. # We can filter for companies where the number of employees is greater
  25. # than the number of chairs.
  26. self.assertQuerysetEqual(
  27. company_query.filter(num_employees__gt=F("num_chairs")), [
  28. {
  29. "num_chairs": 5,
  30. "name": "Example Inc.",
  31. "num_employees": 2300,
  32. },
  33. {
  34. "num_chairs": 1,
  35. "name": "Test GmbH",
  36. "num_employees": 32
  37. },
  38. ],
  39. lambda o: o
  40. )
  41. # We can set one field to have the value of another field
  42. # Make sure we have enough chairs
  43. company_query.update(num_chairs=F("num_employees"))
  44. self.assertQuerysetEqual(
  45. company_query, [
  46. {
  47. "num_chairs": 2300,
  48. "name": "Example Inc.",
  49. "num_employees": 2300
  50. },
  51. {
  52. "num_chairs": 3,
  53. "name": "Foobar Ltd.",
  54. "num_employees": 3
  55. },
  56. {
  57. "num_chairs": 32,
  58. "name": "Test GmbH",
  59. "num_employees": 32
  60. }
  61. ],
  62. lambda o: o
  63. )
  64. # We can perform arithmetic operations in expressions
  65. # Make sure we have 2 spare chairs
  66. company_query.update(num_chairs=F("num_employees")+2)
  67. self.assertQuerysetEqual(
  68. company_query, [
  69. {
  70. 'num_chairs': 2302,
  71. 'name': u'Example Inc.',
  72. 'num_employees': 2300
  73. },
  74. {
  75. 'num_chairs': 5,
  76. 'name': u'Foobar Ltd.',
  77. 'num_employees': 3
  78. },
  79. {
  80. 'num_chairs': 34,
  81. 'name': u'Test GmbH',
  82. 'num_employees': 32
  83. }
  84. ],
  85. lambda o: o,
  86. )
  87. # Law of order of operations is followed
  88. company_query.update(
  89. num_chairs=F('num_employees') + 2 * F('num_employees')
  90. )
  91. self.assertQuerysetEqual(
  92. company_query, [
  93. {
  94. 'num_chairs': 6900,
  95. 'name': u'Example Inc.',
  96. 'num_employees': 2300
  97. },
  98. {
  99. 'num_chairs': 9,
  100. 'name': u'Foobar Ltd.',
  101. 'num_employees': 3
  102. },
  103. {
  104. 'num_chairs': 96,
  105. 'name': u'Test GmbH',
  106. 'num_employees': 32
  107. }
  108. ],
  109. lambda o: o,
  110. )
  111. # Law of order of operations can be overridden by parentheses
  112. company_query.update(
  113. num_chairs=((F('num_employees') + 2) * F('num_employees'))
  114. )
  115. self.assertQuerysetEqual(
  116. company_query, [
  117. {
  118. 'num_chairs': 5294600,
  119. 'name': u'Example Inc.',
  120. 'num_employees': 2300
  121. },
  122. {
  123. 'num_chairs': 15,
  124. 'name': u'Foobar Ltd.',
  125. 'num_employees': 3
  126. },
  127. {
  128. 'num_chairs': 1088,
  129. 'name': u'Test GmbH',
  130. 'num_employees': 32
  131. }
  132. ],
  133. lambda o: o,
  134. )
  135. # The relation of a foreign key can become copied over to an other
  136. # foreign key.
  137. self.assertEqual(
  138. Company.objects.update(point_of_contact=F('ceo')),
  139. 3
  140. )
  141. self.assertQuerysetEqual(
  142. Company.objects.all(), [
  143. "Joe Smith",
  144. "Frank Meyer",
  145. "Max Mustermann",
  146. ],
  147. lambda c: unicode(c.point_of_contact),
  148. )
  149. c = Company.objects.all()[0]
  150. c.point_of_contact = Employee.objects.create(firstname="Guido", lastname="van Rossum")
  151. c.save()
  152. # F Expressions can also span joins
  153. self.assertQuerysetEqual(
  154. Company.objects.filter(ceo__firstname=F("point_of_contact__firstname")), [
  155. "Foobar Ltd.",
  156. "Test GmbH",
  157. ],
  158. lambda c: c.name
  159. )
  160. Company.objects.exclude(
  161. ceo__firstname=F("point_of_contact__firstname")
  162. ).update(name="foo")
  163. self.assertEqual(
  164. Company.objects.exclude(
  165. ceo__firstname=F('point_of_contact__firstname')
  166. ).get().name,
  167. "foo",
  168. )
  169. self.assertRaises(FieldError,
  170. lambda: Company.objects.exclude(
  171. ceo__firstname=F('point_of_contact__firstname')
  172. ).update(name=F('point_of_contact__lastname'))
  173. )
  174. # F expressions can be used to update attributes on single objects
  175. test_gmbh = Company.objects.get(name="Test GmbH")
  176. self.assertEqual(test_gmbh.num_employees, 32)
  177. test_gmbh.num_employees = F("num_employees") + 4
  178. test_gmbh.save()
  179. test_gmbh = Company.objects.get(pk=test_gmbh.pk)
  180. self.assertEqual(test_gmbh.num_employees, 36)
  181. # F expressions cannot be used to update attributes which are foreign
  182. # keys, or attributes which involve joins.
  183. test_gmbh.point_of_contact = None
  184. test_gmbh.save()
  185. self.assertTrue(test_gmbh.point_of_contact is None)
  186. def test():
  187. test_gmbh.point_of_contact = F("ceo")
  188. self.assertRaises(ValueError, test)
  189. test_gmbh.point_of_contact = test_gmbh.ceo
  190. test_gmbh.save()
  191. test_gmbh.name = F("ceo__last_name")
  192. self.assertRaises(FieldError, test_gmbh.save)
  193. # F expressions cannot be used to update attributes on objects which do
  194. # not yet exist in the database
  195. acme = Company(
  196. name="The Acme Widget Co.", num_employees=12, num_chairs=5,
  197. ceo=test_gmbh.ceo
  198. )
  199. acme.num_employees = F("num_employees") + 16
  200. self.assertRaises(TypeError, acme.save)