From a10f3908042a71ec5ef81bf76f0f278ca5e7a596 Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Mon, 11 Feb 2013 02:39:14 -0500 Subject: [PATCH] Fixed #19044 -- Made `DeletionMixin` interpolate its `success_url`. Thanks to nxvl and slurms for the initial patch, ptone for the review and timo for the documentation tweaks. --- django/views/generic/edit.py | 5 +++-- docs/ref/class-based-views/mixins-editing.txt | 7 +++++++ docs/releases/1.6.txt | 4 ++++ tests/regressiontests/generic_views/edit.py | 19 +++++++++++++------ tests/regressiontests/generic_views/urls.py | 2 ++ 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/django/views/generic/edit.py b/django/views/generic/edit.py index 97a6c0a698..5b97fc81c9 100644 --- a/django/views/generic/edit.py +++ b/django/views/generic/edit.py @@ -242,8 +242,9 @@ class DeletionMixin(object): redirects to the success URL. """ self.object = self.get_object() + success_url = self.get_success_url() self.object.delete() - return HttpResponseRedirect(self.get_success_url()) + return HttpResponseRedirect(success_url) # Add support for browsers which only accept GET and POST for now. def post(self, *args, **kwargs): @@ -251,7 +252,7 @@ class DeletionMixin(object): def get_success_url(self): if self.success_url: - return self.success_url + return self.success_url % self.object.__dict__ else: raise ImproperlyConfigured( "No URL to redirect to. Provide a success_url.") diff --git a/docs/ref/class-based-views/mixins-editing.txt b/docs/ref/class-based-views/mixins-editing.txt index bce3c84cb1..844171c93a 100644 --- a/docs/ref/class-based-views/mixins-editing.txt +++ b/docs/ref/class-based-views/mixins-editing.txt @@ -201,6 +201,13 @@ ProcessFormView The url to redirect to when the nominated object has been successfully deleted. + .. versionadded:: 1.6 + + ``success_url`` may contain dictionary string formatting, which + will be interpolated against the object's field attributes. For + example, you could use ``success_url="/parent/%(parent_id)s/"`` to + redirect to a URL composed out of the ``parent_id`` field on a model. + .. method:: get_success_url(obj) Returns the url to redirect to when the nominated object has been diff --git a/docs/releases/1.6.txt b/docs/releases/1.6.txt index f53fa8ac4c..5d615177f4 100644 --- a/docs/releases/1.6.txt +++ b/docs/releases/1.6.txt @@ -64,6 +64,10 @@ Minor features :attr:`~django.core.management.BaseCommand.leave_locale_alone` internal option. See :ref:`management-commands-and-locales` for more details. +* The :attr:`~django.views.generic.edit.DeletionMixin.success_url` of + :class:`~django.views.generic.edit.DeletionMixin` is now interpolated with + its ``object``\'s ``__dict__``. + Backwards incompatible changes in 1.6 ===================================== diff --git a/tests/regressiontests/generic_views/edit.py b/tests/regressiontests/generic_views/edit.py index 0f1eb3cca7..3bacc31ee2 100644 --- a/tests/regressiontests/generic_views/edit.py +++ b/tests/regressiontests/generic_views/edit.py @@ -13,12 +13,12 @@ from .models import Artist, Author class FormMixinTests(TestCase): - def test_initial_data(self): - """ Test instance independence of initial data dict (see #16138) """ - initial_1 = FormMixin().get_initial() - initial_1['foo'] = 'bar' - initial_2 = FormMixin().get_initial() - self.assertNotEqual(initial_1, initial_2) + def test_initial_data(self): + """ Test instance independence of initial data dict (see #16138) """ + initial_1 = FormMixin().get_initial() + initial_1['foo'] = 'bar' + initial_2 = FormMixin().get_initial() + self.assertNotEqual(initial_1, initial_2) class BasicFormTests(TestCase): @@ -283,6 +283,13 @@ class DeleteViewTests(TestCase): self.assertRedirects(res, 'http://testserver/edit/authors/create/') self.assertQuerysetEqual(Author.objects.all(), []) + def test_delete_with_interpolated_redirect(self): + a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'}) + res = self.client.post('/edit/author/%d/delete/interpolate_redirect/' % a.pk) + self.assertEqual(res.status_code, 302) + self.assertRedirects(res, 'http://testserver/edit/authors/create/?deleted=%d' % a.pk) + self.assertQuerysetEqual(Author.objects.all(), []) + def test_delete_with_special_properties(self): a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'}) res = self.client.get('/edit/author/%d/delete/special/' % a.pk) diff --git a/tests/regressiontests/generic_views/urls.py b/tests/regressiontests/generic_views/urls.py index 57309053d3..695b50279a 100644 --- a/tests/regressiontests/generic_views/urls.py +++ b/tests/regressiontests/generic_views/urls.py @@ -97,6 +97,8 @@ urlpatterns = patterns('', views.NaiveAuthorDelete.as_view()), (r'^edit/author/(?P\d+)/delete/redirect/$', views.NaiveAuthorDelete.as_view(success_url='/edit/authors/create/')), + (r'^edit/author/(?P\d+)/delete/interpolate_redirect/$', + views.NaiveAuthorDelete.as_view(success_url='/edit/authors/create/?deleted=%(id)s')), (r'^edit/author/(?P\d+)/delete/$', views.AuthorDelete.as_view()), (r'^edit/author/(?P\d+)/delete/special/$',