test_edit.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. from __future__ import unicode_literals
  2. from unittest import expectedFailure
  3. from django.core.exceptions import ImproperlyConfigured
  4. from django.core.urlresolvers import reverse
  5. from django import forms
  6. from django.test import TestCase
  7. from django.test.client import RequestFactory
  8. from django.views.generic.base import View
  9. from django.views.generic.edit import FormMixin, ModelFormMixin, CreateView
  10. from . import views
  11. from .models import Artist, Author
  12. class FormMixinTests(TestCase):
  13. def test_initial_data(self):
  14. """ Test instance independence of initial data dict (see #16138) """
  15. initial_1 = FormMixin().get_initial()
  16. initial_1['foo'] = 'bar'
  17. initial_2 = FormMixin().get_initial()
  18. self.assertNotEqual(initial_1, initial_2)
  19. def test_get_prefix(self):
  20. """ Test prefix can be set (see #18872) """
  21. test_string = 'test'
  22. rf = RequestFactory()
  23. get_request = rf.get('/')
  24. class TestFormMixin(FormMixin):
  25. request = get_request
  26. default_kwargs = TestFormMixin().get_form_kwargs()
  27. self.assertEqual(None, default_kwargs.get('prefix'))
  28. set_mixin = TestFormMixin()
  29. set_mixin.prefix = test_string
  30. set_kwargs = set_mixin.get_form_kwargs()
  31. self.assertEqual(test_string, set_kwargs.get('prefix'))
  32. class BasicFormTests(TestCase):
  33. urls = 'generic_views.urls'
  34. def test_post_data(self):
  35. res = self.client.post('/contact/', {'name': "Me", 'message': "Hello"})
  36. self.assertRedirects(res, 'http://testserver/list/authors/')
  37. class ModelFormMixinTests(TestCase):
  38. def test_get_form(self):
  39. form_class = views.AuthorGetQuerySetFormView().get_form_class()
  40. self.assertEqual(form_class._meta.model, Author)
  41. def test_get_form_checks_for_object(self):
  42. mixin = ModelFormMixin()
  43. mixin.request = RequestFactory().get('/')
  44. self.assertEqual({'initial': {}, 'prefix': None},
  45. mixin.get_form_kwargs())
  46. class CreateViewTests(TestCase):
  47. urls = 'generic_views.urls'
  48. def test_create(self):
  49. res = self.client.get('/edit/authors/create/')
  50. self.assertEqual(res.status_code, 200)
  51. self.assertIsInstance(res.context['form'], forms.ModelForm)
  52. self.assertIsInstance(res.context['view'], View)
  53. self.assertFalse('object' in res.context)
  54. self.assertFalse('author' in res.context)
  55. self.assertTemplateUsed(res, 'generic_views/author_form.html')
  56. res = self.client.post('/edit/authors/create/',
  57. {'name': 'Randall Munroe', 'slug': 'randall-munroe'})
  58. self.assertEqual(res.status_code, 302)
  59. self.assertRedirects(res, 'http://testserver/list/authors/')
  60. self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe>'])
  61. def test_create_invalid(self):
  62. res = self.client.post('/edit/authors/create/',
  63. {'name': 'A' * 101, 'slug': 'randall-munroe'})
  64. self.assertEqual(res.status_code, 200)
  65. self.assertTemplateUsed(res, 'generic_views/author_form.html')
  66. self.assertEqual(len(res.context['form'].errors), 1)
  67. self.assertEqual(Author.objects.count(), 0)
  68. def test_create_with_object_url(self):
  69. res = self.client.post('/edit/artists/create/',
  70. {'name': 'Rene Magritte'})
  71. self.assertEqual(res.status_code, 302)
  72. artist = Artist.objects.get(name='Rene Magritte')
  73. self.assertRedirects(res, 'http://testserver/detail/artist/%d/' % artist.pk)
  74. self.assertQuerysetEqual(Artist.objects.all(), ['<Artist: Rene Magritte>'])
  75. def test_create_with_redirect(self):
  76. res = self.client.post('/edit/authors/create/redirect/',
  77. {'name': 'Randall Munroe', 'slug': 'randall-munroe'})
  78. self.assertEqual(res.status_code, 302)
  79. self.assertRedirects(res, 'http://testserver/edit/authors/create/')
  80. self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe>'])
  81. def test_create_with_interpolated_redirect(self):
  82. res = self.client.post('/edit/authors/create/interpolate_redirect/',
  83. {'name': 'Randall Munroe', 'slug': 'randall-munroe'})
  84. self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe>'])
  85. self.assertEqual(res.status_code, 302)
  86. pk = Author.objects.all()[0].pk
  87. self.assertRedirects(res, 'http://testserver/edit/author/%d/update/' % pk)
  88. def test_create_with_special_properties(self):
  89. res = self.client.get('/edit/authors/create/special/')
  90. self.assertEqual(res.status_code, 200)
  91. self.assertIsInstance(res.context['form'], views.AuthorForm)
  92. self.assertFalse('object' in res.context)
  93. self.assertFalse('author' in res.context)
  94. self.assertTemplateUsed(res, 'generic_views/form.html')
  95. res = self.client.post('/edit/authors/create/special/',
  96. {'name': 'Randall Munroe', 'slug': 'randall-munroe'})
  97. self.assertEqual(res.status_code, 302)
  98. obj = Author.objects.get(slug='randall-munroe')
  99. self.assertRedirects(res, reverse('author_detail', kwargs={'pk': obj.pk}))
  100. self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe>'])
  101. def test_create_without_redirect(self):
  102. try:
  103. self.client.post('/edit/authors/create/naive/',
  104. {'name': 'Randall Munroe', 'slug': 'randall-munroe'})
  105. self.fail('Should raise exception -- No redirect URL provided, and no get_absolute_url provided')
  106. except ImproperlyConfigured:
  107. pass
  108. def test_create_restricted(self):
  109. res = self.client.post('/edit/authors/create/restricted/',
  110. {'name': 'Randall Munroe', 'slug': 'randall-munroe'})
  111. self.assertEqual(res.status_code, 302)
  112. self.assertRedirects(res, 'http://testserver/accounts/login/?next=/edit/authors/create/restricted/')
  113. def test_create_view_with_restricted_fields(self):
  114. class MyCreateView(CreateView):
  115. model = Author
  116. fields = ['name']
  117. self.assertEqual(list(MyCreateView().get_form_class().base_fields),
  118. ['name'])
  119. def test_create_view_all_fields(self):
  120. class MyCreateView(CreateView):
  121. model = Author
  122. fields = '__all__'
  123. self.assertEqual(list(MyCreateView().get_form_class().base_fields),
  124. ['name', 'slug'])
  125. def test_create_view_without_explicit_fields(self):
  126. class MyCreateView(CreateView):
  127. model = Author
  128. message = (
  129. "Using ModelFormMixin (base class of MyCreateView) without the "
  130. "'fields' attribute is prohibited."
  131. )
  132. with self.assertRaisesMessage(ImproperlyConfigured, message):
  133. MyCreateView().get_form_class()
  134. class UpdateViewTests(TestCase):
  135. urls = 'generic_views.urls'
  136. def test_update_post(self):
  137. a = Author.objects.create(
  138. name='Randall Munroe',
  139. slug='randall-munroe',
  140. )
  141. res = self.client.get('/edit/author/%d/update/' % a.pk)
  142. self.assertEqual(res.status_code, 200)
  143. self.assertIsInstance(res.context['form'], forms.ModelForm)
  144. self.assertEqual(res.context['object'], Author.objects.get(pk=a.pk))
  145. self.assertEqual(res.context['author'], Author.objects.get(pk=a.pk))
  146. self.assertTemplateUsed(res, 'generic_views/author_form.html')
  147. # Modification with both POST and PUT (browser compatible)
  148. res = self.client.post('/edit/author/%d/update/' % a.pk,
  149. {'name': 'Randall Munroe (xkcd)', 'slug': 'randall-munroe'})
  150. self.assertEqual(res.status_code, 302)
  151. self.assertRedirects(res, 'http://testserver/list/authors/')
  152. self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (xkcd)>'])
  153. @expectedFailure
  154. def test_update_put(self):
  155. a = Author.objects.create(
  156. name='Randall Munroe',
  157. slug='randall-munroe',
  158. )
  159. res = self.client.get('/edit/author/%d/update/' % a.pk)
  160. self.assertEqual(res.status_code, 200)
  161. self.assertTemplateUsed(res, 'generic_views/author_form.html')
  162. res = self.client.put('/edit/author/%d/update/' % a.pk,
  163. {'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'})
  164. # Here is the expected failure. PUT data are not processed in any special
  165. # way by django. So the request will equal to a POST without data, hence
  166. # the form will be invalid and redisplayed with errors (status code 200).
  167. # See also #12635
  168. self.assertEqual(res.status_code, 302)
  169. self.assertRedirects(res, 'http://testserver/list/authors/')
  170. self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (author of xkcd)>'])
  171. def test_update_invalid(self):
  172. a = Author.objects.create(
  173. name='Randall Munroe',
  174. slug='randall-munroe',
  175. )
  176. res = self.client.post('/edit/author/%d/update/' % a.pk,
  177. {'name': 'A' * 101, 'slug': 'randall-munroe'})
  178. self.assertEqual(res.status_code, 200)
  179. self.assertTemplateUsed(res, 'generic_views/author_form.html')
  180. self.assertEqual(len(res.context['form'].errors), 1)
  181. self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe>'])
  182. def test_update_with_object_url(self):
  183. a = Artist.objects.create(name='Rene Magritte')
  184. res = self.client.post('/edit/artists/%d/update/' % a.pk,
  185. {'name': 'Rene Magritte'})
  186. self.assertEqual(res.status_code, 302)
  187. self.assertRedirects(res, 'http://testserver/detail/artist/%d/' % a.pk)
  188. self.assertQuerysetEqual(Artist.objects.all(), ['<Artist: Rene Magritte>'])
  189. def test_update_with_redirect(self):
  190. a = Author.objects.create(
  191. name='Randall Munroe',
  192. slug='randall-munroe',
  193. )
  194. res = self.client.post('/edit/author/%d/update/redirect/' % a.pk,
  195. {'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'})
  196. self.assertEqual(res.status_code, 302)
  197. self.assertRedirects(res, 'http://testserver/edit/authors/create/')
  198. self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (author of xkcd)>'])
  199. def test_update_with_interpolated_redirect(self):
  200. a = Author.objects.create(
  201. name='Randall Munroe',
  202. slug='randall-munroe',
  203. )
  204. res = self.client.post('/edit/author/%d/update/interpolate_redirect/' % a.pk,
  205. {'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'})
  206. self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (author of xkcd)>'])
  207. self.assertEqual(res.status_code, 302)
  208. pk = Author.objects.all()[0].pk
  209. self.assertRedirects(res, 'http://testserver/edit/author/%d/update/' % pk)
  210. def test_update_with_special_properties(self):
  211. a = Author.objects.create(
  212. name='Randall Munroe',
  213. slug='randall-munroe',
  214. )
  215. res = self.client.get('/edit/author/%d/update/special/' % a.pk)
  216. self.assertEqual(res.status_code, 200)
  217. self.assertIsInstance(res.context['form'], views.AuthorForm)
  218. self.assertEqual(res.context['object'], Author.objects.get(pk=a.pk))
  219. self.assertEqual(res.context['thingy'], Author.objects.get(pk=a.pk))
  220. self.assertFalse('author' in res.context)
  221. self.assertTemplateUsed(res, 'generic_views/form.html')
  222. res = self.client.post('/edit/author/%d/update/special/' % a.pk,
  223. {'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'})
  224. self.assertEqual(res.status_code, 302)
  225. self.assertRedirects(res, 'http://testserver/detail/author/%d/' % a.pk)
  226. self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (author of xkcd)>'])
  227. def test_update_without_redirect(self):
  228. a = Author.objects.create(
  229. name='Randall Munroe',
  230. slug='randall-munroe',
  231. )
  232. # Should raise exception -- No redirect URL provided, and no
  233. # get_absolute_url provided
  234. with self.assertRaises(ImproperlyConfigured):
  235. self.client.post('/edit/author/%d/update/naive/' % a.pk,
  236. {'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'})
  237. def test_update_get_object(self):
  238. a = Author.objects.create(
  239. pk=1,
  240. name='Randall Munroe',
  241. slug='randall-munroe',
  242. )
  243. res = self.client.get('/edit/author/update/')
  244. self.assertEqual(res.status_code, 200)
  245. self.assertIsInstance(res.context['form'], forms.ModelForm)
  246. self.assertIsInstance(res.context['view'], View)
  247. self.assertEqual(res.context['object'], Author.objects.get(pk=a.pk))
  248. self.assertEqual(res.context['author'], Author.objects.get(pk=a.pk))
  249. self.assertTemplateUsed(res, 'generic_views/author_form.html')
  250. # Modification with both POST and PUT (browser compatible)
  251. res = self.client.post('/edit/author/update/',
  252. {'name': 'Randall Munroe (xkcd)', 'slug': 'randall-munroe'})
  253. self.assertEqual(res.status_code, 302)
  254. self.assertRedirects(res, 'http://testserver/list/authors/')
  255. self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (xkcd)>'])
  256. class DeleteViewTests(TestCase):
  257. urls = 'generic_views.urls'
  258. def test_delete_by_post(self):
  259. a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'})
  260. res = self.client.get('/edit/author/%d/delete/' % a.pk)
  261. self.assertEqual(res.status_code, 200)
  262. self.assertEqual(res.context['object'], Author.objects.get(pk=a.pk))
  263. self.assertEqual(res.context['author'], Author.objects.get(pk=a.pk))
  264. self.assertTemplateUsed(res, 'generic_views/author_confirm_delete.html')
  265. # Deletion with POST
  266. res = self.client.post('/edit/author/%d/delete/' % a.pk)
  267. self.assertEqual(res.status_code, 302)
  268. self.assertRedirects(res, 'http://testserver/list/authors/')
  269. self.assertQuerysetEqual(Author.objects.all(), [])
  270. def test_delete_by_delete(self):
  271. # Deletion with browser compatible DELETE method
  272. a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'})
  273. res = self.client.delete('/edit/author/%d/delete/' % a.pk)
  274. self.assertEqual(res.status_code, 302)
  275. self.assertRedirects(res, 'http://testserver/list/authors/')
  276. self.assertQuerysetEqual(Author.objects.all(), [])
  277. def test_delete_with_redirect(self):
  278. a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'})
  279. res = self.client.post('/edit/author/%d/delete/redirect/' % a.pk)
  280. self.assertEqual(res.status_code, 302)
  281. self.assertRedirects(res, 'http://testserver/edit/authors/create/')
  282. self.assertQuerysetEqual(Author.objects.all(), [])
  283. def test_delete_with_interpolated_redirect(self):
  284. a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'})
  285. res = self.client.post('/edit/author/%d/delete/interpolate_redirect/' % a.pk)
  286. self.assertEqual(res.status_code, 302)
  287. self.assertRedirects(res, 'http://testserver/edit/authors/create/?deleted=%d' % a.pk)
  288. self.assertQuerysetEqual(Author.objects.all(), [])
  289. def test_delete_with_special_properties(self):
  290. a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'})
  291. res = self.client.get('/edit/author/%d/delete/special/' % a.pk)
  292. self.assertEqual(res.status_code, 200)
  293. self.assertEqual(res.context['object'], Author.objects.get(pk=a.pk))
  294. self.assertEqual(res.context['thingy'], Author.objects.get(pk=a.pk))
  295. self.assertFalse('author' in res.context)
  296. self.assertTemplateUsed(res, 'generic_views/confirm_delete.html')
  297. res = self.client.post('/edit/author/%d/delete/special/' % a.pk)
  298. self.assertEqual(res.status_code, 302)
  299. self.assertRedirects(res, 'http://testserver/list/authors/')
  300. self.assertQuerysetEqual(Author.objects.all(), [])
  301. def test_delete_without_redirect(self):
  302. a = Author.objects.create(
  303. name='Randall Munroe',
  304. slug='randall-munroe',
  305. )
  306. # Should raise exception -- No redirect URL provided, and no
  307. # get_absolute_url provided
  308. with self.assertRaises(ImproperlyConfigured):
  309. self.client.post('/edit/author/%d/delete/naive/' % a.pk)