PageRenderTime 63ms CodeModel.GetById 0ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/modeltests/delete/tests.py

https://code.google.com/p/mango-py/
Python | 253 lines | 193 code | 45 blank | 15 comment | 6 complexity | e56abe6f20a13f6433125ec71831c07e MD5 | raw file
Possible License(s): BSD-3-Clause
  1. from django.db import models, IntegrityError
  2. from django.test import TestCase, skipUnlessDBFeature, skipIfDBFeature
  3. from modeltests.delete.models import (R, RChild, S, T, U, A, M, MR, MRNull,
  4. create_a, get_default_r, User, Avatar, HiddenUser, HiddenUserProfile)
  5. class OnDeleteTests(TestCase):
  6. def setUp(self):
  7. self.DEFAULT = get_default_r()
  8. def test_auto(self):
  9. a = create_a('auto')
  10. a.auto.delete()
  11. self.assertFalse(A.objects.filter(name='auto').exists())
  12. def test_auto_nullable(self):
  13. a = create_a('auto_nullable')
  14. a.auto_nullable.delete()
  15. self.assertFalse(A.objects.filter(name='auto_nullable').exists())
  16. def test_setvalue(self):
  17. a = create_a('setvalue')
  18. a.setvalue.delete()
  19. a = A.objects.get(pk=a.pk)
  20. self.assertEqual(self.DEFAULT, a.setvalue)
  21. def test_setnull(self):
  22. a = create_a('setnull')
  23. a.setnull.delete()
  24. a = A.objects.get(pk=a.pk)
  25. self.assertEqual(None, a.setnull)
  26. def test_setdefault(self):
  27. a = create_a('setdefault')
  28. a.setdefault.delete()
  29. a = A.objects.get(pk=a.pk)
  30. self.assertEqual(self.DEFAULT, a.setdefault)
  31. def test_setdefault_none(self):
  32. a = create_a('setdefault_none')
  33. a.setdefault_none.delete()
  34. a = A.objects.get(pk=a.pk)
  35. self.assertEqual(None, a.setdefault_none)
  36. def test_cascade(self):
  37. a = create_a('cascade')
  38. a.cascade.delete()
  39. self.assertFalse(A.objects.filter(name='cascade').exists())
  40. def test_cascade_nullable(self):
  41. a = create_a('cascade_nullable')
  42. a.cascade_nullable.delete()
  43. self.assertFalse(A.objects.filter(name='cascade_nullable').exists())
  44. def test_protect(self):
  45. a = create_a('protect')
  46. self.assertRaises(IntegrityError, a.protect.delete)
  47. def test_do_nothing(self):
  48. # Testing DO_NOTHING is a bit harder: It would raise IntegrityError for a normal model,
  49. # so we connect to pre_delete and set the fk to a known value.
  50. replacement_r = R.objects.create()
  51. def check_do_nothing(sender, **kwargs):
  52. obj = kwargs['instance']
  53. obj.donothing_set.update(donothing=replacement_r)
  54. models.signals.pre_delete.connect(check_do_nothing)
  55. a = create_a('do_nothing')
  56. a.donothing.delete()
  57. a = A.objects.get(pk=a.pk)
  58. self.assertEqual(replacement_r, a.donothing)
  59. models.signals.pre_delete.disconnect(check_do_nothing)
  60. def test_inheritance_cascade_up(self):
  61. child = RChild.objects.create()
  62. child.delete()
  63. self.assertFalse(R.objects.filter(pk=child.pk).exists())
  64. def test_inheritance_cascade_down(self):
  65. child = RChild.objects.create()
  66. parent = child.r_ptr
  67. parent.delete()
  68. self.assertFalse(RChild.objects.filter(pk=child.pk).exists())
  69. def test_cascade_from_child(self):
  70. a = create_a('child')
  71. a.child.delete()
  72. self.assertFalse(A.objects.filter(name='child').exists())
  73. self.assertFalse(R.objects.filter(pk=a.child_id).exists())
  74. def test_cascade_from_parent(self):
  75. a = create_a('child')
  76. R.objects.get(pk=a.child_id).delete()
  77. self.assertFalse(A.objects.filter(name='child').exists())
  78. self.assertFalse(RChild.objects.filter(pk=a.child_id).exists())
  79. def test_setnull_from_child(self):
  80. a = create_a('child_setnull')
  81. a.child_setnull.delete()
  82. self.assertFalse(R.objects.filter(pk=a.child_setnull_id).exists())
  83. a = A.objects.get(pk=a.pk)
  84. self.assertEqual(None, a.child_setnull)
  85. def test_setnull_from_parent(self):
  86. a = create_a('child_setnull')
  87. R.objects.get(pk=a.child_setnull_id).delete()
  88. self.assertFalse(RChild.objects.filter(pk=a.child_setnull_id).exists())
  89. a = A.objects.get(pk=a.pk)
  90. self.assertEqual(None, a.child_setnull)
  91. def test_o2o_setnull(self):
  92. a = create_a('o2o_setnull')
  93. a.o2o_setnull.delete()
  94. a = A.objects.get(pk=a.pk)
  95. self.assertEqual(None, a.o2o_setnull)
  96. class DeletionTests(TestCase):
  97. def test_m2m(self):
  98. m = M.objects.create()
  99. r = R.objects.create()
  100. MR.objects.create(m=m, r=r)
  101. r.delete()
  102. self.assertFalse(MR.objects.exists())
  103. r = R.objects.create()
  104. MR.objects.create(m=m, r=r)
  105. m.delete()
  106. self.assertFalse(MR.objects.exists())
  107. m = M.objects.create()
  108. r = R.objects.create()
  109. m.m2m.add(r)
  110. r.delete()
  111. through = M._meta.get_field('m2m').rel.through
  112. self.assertFalse(through.objects.exists())
  113. r = R.objects.create()
  114. m.m2m.add(r)
  115. m.delete()
  116. self.assertFalse(through.objects.exists())
  117. m = M.objects.create()
  118. r = R.objects.create()
  119. MRNull.objects.create(m=m, r=r)
  120. r.delete()
  121. self.assertFalse(not MRNull.objects.exists())
  122. self.assertFalse(m.m2m_through_null.exists())
  123. def test_bulk(self):
  124. from django.db.models.sql.constants import GET_ITERATOR_CHUNK_SIZE
  125. s = S.objects.create(r=R.objects.create())
  126. for i in xrange(2*GET_ITERATOR_CHUNK_SIZE):
  127. T.objects.create(s=s)
  128. # 1 (select related `T` instances)
  129. # + 1 (select related `U` instances)
  130. # + 2 (delete `T` instances in batches)
  131. # + 1 (delete `s`)
  132. self.assertNumQueries(5, s.delete)
  133. self.assertFalse(S.objects.exists())
  134. def test_instance_update(self):
  135. deleted = []
  136. related_setnull_sets = []
  137. def pre_delete(sender, **kwargs):
  138. obj = kwargs['instance']
  139. deleted.append(obj)
  140. if isinstance(obj, R):
  141. related_setnull_sets.append(list(a.pk for a in obj.setnull_set.all()))
  142. models.signals.pre_delete.connect(pre_delete)
  143. a = create_a('update_setnull')
  144. a.setnull.delete()
  145. a = create_a('update_cascade')
  146. a.cascade.delete()
  147. for obj in deleted:
  148. self.assertEqual(None, obj.pk)
  149. for pk_list in related_setnull_sets:
  150. for a in A.objects.filter(id__in=pk_list):
  151. self.assertEqual(None, a.setnull)
  152. models.signals.pre_delete.disconnect(pre_delete)
  153. def test_deletion_order(self):
  154. pre_delete_order = []
  155. post_delete_order = []
  156. def log_post_delete(sender, **kwargs):
  157. pre_delete_order.append((sender, kwargs['instance'].pk))
  158. def log_pre_delete(sender, **kwargs):
  159. post_delete_order.append((sender, kwargs['instance'].pk))
  160. models.signals.post_delete.connect(log_post_delete)
  161. models.signals.pre_delete.connect(log_pre_delete)
  162. r = R.objects.create(pk=1)
  163. s1 = S.objects.create(pk=1, r=r)
  164. s2 = S.objects.create(pk=2, r=r)
  165. t1 = T.objects.create(pk=1, s=s1)
  166. t2 = T.objects.create(pk=2, s=s2)
  167. r.delete()
  168. self.assertEqual(
  169. pre_delete_order, [(T, 2), (T, 1), (S, 2), (S, 1), (R, 1)]
  170. )
  171. self.assertEqual(
  172. post_delete_order, [(T, 1), (T, 2), (S, 1), (S, 2), (R, 1)]
  173. )
  174. models.signals.post_delete.disconnect(log_post_delete)
  175. models.signals.post_delete.disconnect(log_pre_delete)
  176. @skipUnlessDBFeature("can_defer_constraint_checks")
  177. def test_can_defer_constraint_checks(self):
  178. u = User.objects.create(
  179. avatar=Avatar.objects.create()
  180. )
  181. a = Avatar.objects.get(pk=u.avatar_id)
  182. # 1 query to find the users for the avatar.
  183. # 1 query to delete the user
  184. # 1 query to delete the avatar
  185. # The important thing is that when we can defer constraint checks there
  186. # is no need to do an UPDATE on User.avatar to null it out.
  187. self.assertNumQueries(3, a.delete)
  188. self.assertFalse(User.objects.exists())
  189. self.assertFalse(Avatar.objects.exists())
  190. @skipIfDBFeature("can_defer_constraint_checks")
  191. def test_cannot_defer_constraint_checks(self):
  192. u = User.objects.create(
  193. avatar=Avatar.objects.create()
  194. )
  195. a = Avatar.objects.get(pk=u.avatar_id)
  196. # 1 query to find the users for the avatar.
  197. # 1 query to delete the user
  198. # 1 query to null out user.avatar, because we can't defer the constraint
  199. # 1 query to delete the avatar
  200. self.assertNumQueries(4, a.delete)
  201. self.assertFalse(User.objects.exists())
  202. self.assertFalse(Avatar.objects.exists())
  203. def test_hidden_related(self):
  204. r = R.objects.create()
  205. h = HiddenUser.objects.create(r=r)
  206. p = HiddenUserProfile.objects.create(user=h)
  207. r.delete()
  208. self.assertEqual(HiddenUserProfile.objects.count(), 0)