Ticket #13953: django-callable-crud-redirect.diff

File django-callable-crud-redirect.diff, 8.3 KB (added by Alberto Donato <alberto.donato@…>, 5 years ago)
  • django/views/generic/create_update.py

     
    4545    raise GenericViewError("Generic view must be called with either a model or"
    4646                           " form_class argument.")
    4747
    48 def redirect(post_save_redirect, obj):
     48def expand_redirect(post_save_redirect, obj):
    4949    """
    50     Returns a HttpResponseRedirect to ``post_save_redirect``.
     50    Returns a string with a redirect to ``post_save_redirect``.
    5151
    5252    ``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
    5455
    5556    If ``post_save_redirect`` is None, then redirect to ``obj``'s URL returned
    5657    by ``get_absolute_url()``.  If ``obj`` has no ``get_absolute_url`` method,
    5758    then raise ImproperlyConfigured.
    5859
    5960    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.
    6162    """
     63
    6264    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__
    6469    elif hasattr(obj, 'get_absolute_url'):
    65         return HttpResponseRedirect(obj.get_absolute_url())
     70        return obj.get_absolute_url()
    6671    else:
    6772        raise ImproperlyConfigured(
    6873            "No URL to redirect to.  Either pass a post_save_redirect"
     
    115120            msg = ugettext("The %(verbose_name)s was created successfully.") %\
    116121                                    {"verbose_name": model._meta.verbose_name}
    117122            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))
    119124    else:
    120125        form = form_class()
    121126
     
    158163            msg = ugettext("The %(verbose_name)s was updated successfully.") %\
    159164                                    {"verbose_name": model._meta.verbose_name}
    160165            messages.success(request, msg, fail_silently=True)
    161             return redirect(post_save_redirect, obj)
     166            return HttpResponseRedirect(expand_redirect(post_save_redirect, obj))
    162167    else:
    163168        form = form_class(instance=obj)
    164169
     
    197202    obj = lookup_object(model, object_id, slug, slug_field)
    198203
    199204    if request.method == 'POST':
     205        redirect_url = expand_redirect(post_delete_redirect, obj)
    200206        obj.delete()
    201207        msg = ugettext("The %(verbose_name)s was deleted.") %\
    202208                                    {"verbose_name": model._meta.verbose_name}
    203209        messages.success(request, msg, fail_silently=True)
    204         return HttpResponseRedirect(post_delete_redirect)
     210        return HttpResponseRedirect(redirect_url)
    205211    else:
    206212        if not template_name:
    207213            template_name = "%s/%s_confirm_delete.html" % (model._meta.app_label, model._meta.object_name.lower())
  • tests/regressiontests/views/tests/generic/create_update.py

     
    163163        self.assertEqual(num_articles - 1, self.article_model.objects.count(),
    164164                         "An Article should have been deleted.")
    165165
     166class 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
    166214class NoPostSaveNoAbsoluteUrl(PostSaveRedirectTests):
    167215    """
    168216    Tests that when no post_save_redirect is passed and no get_absolute_url
  • tests/regressiontests/views/views.py

     
    5757    return render_to_response('debug/template_exception.html',
    5858        {'arg': except_args[int(n)]})
    5959
     60
     61def 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

     
    22from os import path
    33
    44from django.conf.urls.defaults import *
     5from django.core.urlresolvers import reverse
    56
    67from models import *
    78import views
     
    9293        dict(post_delete_redirect='/views/create_update/', slug_field='slug',
    9394             model=Article)),
    9495
     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
    95107    # No post_save_redirect and no get_absolute_url on model.
    96108    (r'^create_update/no_redirect/create/article/$', 'create_object',
    97109        dict(model=Article)),
     
    122134urlpatterns += patterns('regressiontests.views.views',
    123135    url(r'view_exception/(?P<n>\d+)/$', 'view_exception', name='view_exception'),
    124136    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'),
    125138)
Back to Top