Ticket #13953: django-callable-crud-redirect.diff
File django-callable-crud-redirect.diff, 8.3 KB (added by , 14 years ago) |
---|
-
django/views/generic/create_update.py
45 45 raise GenericViewError("Generic view must be called with either a model or" 46 46 " form_class argument.") 47 47 48 def redirect(post_save_redirect, obj):48 def expand_redirect(post_save_redirect, obj): 49 49 """ 50 Returns a HttpResponseRedirect to ``post_save_redirect``.50 Returns a string with a redirect to ``post_save_redirect``. 51 51 52 52 ``post_save_redirect`` should be a string, and can contain named string- 53 substitution place holders of ``obj`` field names. 53 substitution place holders of ``obj`` field names or a callable which 54 receives ``obj`` as parameter and returns the url as string 54 55 55 56 If ``post_save_redirect`` is None, then redirect to ``obj``'s URL returned 56 57 by ``get_absolute_url()``. If ``obj`` has no ``get_absolute_url`` method, 57 58 then raise ImproperlyConfigured. 58 59 59 60 This function is meant to handle the post_save_redirect parameter to the 60 ``create_object`` and ``update_object`` views.61 ``create_object``, ``update_object`` and ``delete_object`` views. 61 62 """ 63 62 64 if post_save_redirect: 63 return HttpResponseRedirect(post_save_redirect % obj.__dict__) 65 if callable(post_save_redirect): 66 return post_save_redirect(obj) 67 else: 68 return post_save_redirect % obj.__dict__ 64 69 elif hasattr(obj, 'get_absolute_url'): 65 return HttpResponseRedirect(obj.get_absolute_url())70 return obj.get_absolute_url() 66 71 else: 67 72 raise ImproperlyConfigured( 68 73 "No URL to redirect to. Either pass a post_save_redirect" … … 115 120 msg = ugettext("The %(verbose_name)s was created successfully.") %\ 116 121 {"verbose_name": model._meta.verbose_name} 117 122 messages.success(request, msg, fail_silently=True) 118 return redirect(post_save_redirect, new_object)123 return HttpResponseRedirect(expand_redirect(post_save_redirect, new_object)) 119 124 else: 120 125 form = form_class() 121 126 … … 158 163 msg = ugettext("The %(verbose_name)s was updated successfully.") %\ 159 164 {"verbose_name": model._meta.verbose_name} 160 165 messages.success(request, msg, fail_silently=True) 161 return redirect(post_save_redirect, obj)166 return HttpResponseRedirect(expand_redirect(post_save_redirect, obj)) 162 167 else: 163 168 form = form_class(instance=obj) 164 169 … … 197 202 obj = lookup_object(model, object_id, slug, slug_field) 198 203 199 204 if request.method == 'POST': 205 redirect_url = expand_redirect(post_delete_redirect, obj) 200 206 obj.delete() 201 207 msg = ugettext("The %(verbose_name)s was deleted.") %\ 202 208 {"verbose_name": model._meta.verbose_name} 203 209 messages.success(request, msg, fail_silently=True) 204 return HttpResponseRedirect( post_delete_redirect)210 return HttpResponseRedirect(redirect_url) 205 211 else: 206 212 if not template_name: 207 213 template_name = "%s/%s_confirm_delete.html" % (model._meta.app_label, model._meta.object_name.lower()) -
tests/regressiontests/views/tests/generic/create_update.py
163 163 self.assertEqual(num_articles - 1, self.article_model.objects.count(), 164 164 "An Article should have been deleted.") 165 165 166 class PostSaveCallableRedirectTests(TestCase): 167 """ 168 Verifies that the views redirect to the correct locations when 169 using a callable to calculate the redirect URL. 170 """ 171 172 fixtures = ['testdata.json'] 173 article_model = Article 174 175 create_url = '/views/create_update/callable_redirect/create/article/' 176 update_url = '/views/create_update/callable_redirect/update/article/old_article/' 177 delete_url = '/views/create_update/callable_redirect/delete/article/old_article/' 178 179 create_redirect = '/views/crud_redirect_target/my-first-article/' 180 update_redirect = '/views/crud_redirect_target/another-article-slug/' 181 delete_redirect = '/views/crud_redirect_target/old_article/' 182 183 def test_create_article(self): 184 num_articles = self.article_model.objects.count() 185 response = self.client.post(self.create_url, { 186 'title': 'My First Article', 187 'slug': 'my-first-article', 188 'author': '1', 189 'date_created': datetime.datetime(2007, 6, 25), 190 }) 191 self.assertRedirects(response, self.create_redirect) 192 self.assertEqual(num_articles + 1, self.article_model.objects.count(), 193 "A new Article should have been created.") 194 195 def test_update_article(self): 196 num_articles = self.article_model.objects.count() 197 response = self.client.post(self.update_url, { 198 'title': 'Another Article', 199 'slug': 'another-article-slug', 200 'author': 1, 201 'date_created': datetime.datetime(2007, 6, 25), 202 }) 203 self.assertRedirects(response, self.update_redirect) 204 self.assertEqual(num_articles, self.article_model.objects.count(), 205 "A new Article should not have been created.") 206 207 def test_delete_article(self): 208 num_articles = self.article_model.objects.count() 209 response = self.client.post(self.delete_url) 210 self.assertRedirects(response, self.delete_redirect) 211 self.assertEqual(num_articles - 1, self.article_model.objects.count(), 212 "An Article should have been deleted.") 213 166 214 class NoPostSaveNoAbsoluteUrl(PostSaveRedirectTests): 167 215 """ 168 216 Tests that when no post_save_redirect is passed and no get_absolute_url -
tests/regressiontests/views/views.py
57 57 return render_to_response('debug/template_exception.html', 58 58 {'arg': except_args[int(n)]}) 59 59 60 61 def crud_redirect_target(request, slug): 62 """ 63 Dummy view used as target for CRUD views redirects 64 """ 65 return HttpResponse('<html><body>Redirected from CRUD view, slug: %s</body></html>' % slug) -
tests/regressiontests/views/urls.py
2 2 from os import path 3 3 4 4 from django.conf.urls.defaults import * 5 from django.core.urlresolvers import reverse 5 6 6 7 from models import * 7 8 import views … … 92 93 dict(post_delete_redirect='/views/create_update/', slug_field='slug', 93 94 model=Article)), 94 95 96 # Redirect using a callable 97 (r'^create_update/callable_redirect/create/article/$', 'create_object', 98 dict(post_save_redirect=lambda obj: reverse('crud_redirect_target', args=(obj.slug,)), 99 model=Article)), 100 (r'^create_update/callable_redirect/update/article/(?P<slug>[-\w]+)/$', 'update_object', 101 dict(post_save_redirect=lambda obj: reverse('crud_redirect_target', args=(obj.slug,)), 102 slug_field='slug', model=Article)), 103 (r'^create_update/callable_redirect/delete/article/(?P<slug>[-\w]+)/$', 'delete_object', 104 dict(post_delete_redirect=lambda obj: reverse('crud_redirect_target', args=(obj.slug,)), 105 slug_field='slug', model=Article)), 106 95 107 # No post_save_redirect and no get_absolute_url on model. 96 108 (r'^create_update/no_redirect/create/article/$', 'create_object', 97 109 dict(model=Article)), … … 122 134 urlpatterns += patterns('regressiontests.views.views', 123 135 url(r'view_exception/(?P<n>\d+)/$', 'view_exception', name='view_exception'), 124 136 url(r'template_exception/(?P<n>\d+)/$', 'template_exception', name='template_exception'), 137 url(r'crud_redirect_target/(?P<slug>[-\w]+)/$', 'crud_redirect_target', name='crud_redirect_target'), 125 138 )