Loading django/views/generic/edit.py +19 −2 Original line number Diff line number Diff line import inspect import re import warnings from django.core.exceptions import ImproperlyConfigured Loading Loading @@ -162,7 +163,15 @@ class ModelFormMixin(FormMixin, SingleObjectMixin): Returns the supplied URL. """ if self.success_url: if re.search(r'%\([^\)]+\)', self.success_url): warnings.warn( "%()s placeholder style in success_url is deprecated. " "Please replace them by the {} Python format syntax.", RemovedInDjango20Warning, stacklevel=2 ) url = self.success_url % self.object.__dict__ else: url = self.success_url.format(**self.object.__dict__) else: try: url = self.object.get_absolute_url() Loading Loading @@ -288,7 +297,15 @@ class DeletionMixin(object): def get_success_url(self): if self.success_url: if re.search(r'%\([^\)]+\)', self.success_url): warnings.warn( "%()s placeholder style in success_url is deprecated. " "Please replace them by the {} Python format syntax.", RemovedInDjango20Warning, stacklevel=2 ) return self.success_url % self.object.__dict__ else: return self.success_url.format(**self.object.__dict__) else: raise ImproperlyConfigured( "No URL to redirect to. Provide a success_url.") Loading docs/internals/deprecation.txt +3 −0 Original line number Diff line number Diff line Loading @@ -158,6 +158,9 @@ details on these changes. and ``Storage.save()`` to be defined without a ``max_length`` argument will be removed. * Support for the legacy ``%(<foo>)s`` syntax in ``ModelFormMixin.success_url`` will be removed. .. _deprecation-removed-in-1.9: 1.9 Loading docs/ref/class-based-views/mixins-editing.txt +14 −2 Original line number Diff line number Diff line Loading @@ -160,9 +160,15 @@ ModelFormMixin ``success_url`` may contain dictionary string formatting, which will be interpolated against the object's field attributes. For example, you could use ``success_url="/polls/%(slug)s/"`` to example, you could use ``success_url="/polls/{slug}/"`` to redirect to a URL composed out of the ``slug`` field on a model. .. versionchanged:: 1.8 Support for the new brace-based Python formatting syntax has been added. The old ``%(slug)s`` placeholder syntax support has been deprecated and will be removed in Django 2.0. .. method:: get_form_class() Retrieve the form class to instantiate. If Loading Loading @@ -248,9 +254,15 @@ DeletionMixin ``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 could use ``success_url="/parent/{parent_id}/"`` to redirect to a URL composed out of the ``parent_id`` field on a model. .. versionchanged:: 1.8 Support for the new brace-based Python formatting syntax has been added. The old ``%(slug)s`` placeholder syntax support has been deprecated and will be removed in Django 2.0. .. method:: get_success_url() Returns the url to redirect to when the nominated object has been Loading docs/releases/1.8.txt +12 −0 Original line number Diff line number Diff line Loading @@ -388,6 +388,11 @@ Generic Views require a ``form_class`` to be provided anymore. If not provided ``form_class`` defaults to :meth:`~django.views.generic.edit.FormMixin.get_form_class()`. * Placeholders in :attr:`ModelFormMixin.success_url <django.views.generic.edit.ModelFormMixin.success_url>` now support the Python :py:meth:`str.format()` syntax. The legacy ``%(<foo>)s`` syntax is still supported but will be removed in Django 2.0. Internationalization ^^^^^^^^^^^^^^^^^^^^ Loading Loading @@ -1550,6 +1555,13 @@ will be removed in Django 2.0. Using a single equals sign with the ``{% if %}`` template tag for equality testing was undocumented and untested. It's now deprecated in favor of ``==``. ``%(<foo>)s`` syntax in ``ModelFormMixin.success_url`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The legacy ``%(<foo>)s`` syntax in :attr:`ModelFormMixin.success_url <django.views.generic.edit.ModelFormMixin.success_url>` is deprecated and will be removed in Django 2.0. .. removed-features-1.8: Features removed in 1.8 Loading tests/generic_views/test_edit.py +35 −7 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ import warnings from django.core.exceptions import ImproperlyConfigured from django.core.urlresolvers import reverse from django import forms from django.test import TestCase, override_settings from django.test import TestCase, ignore_warnings, override_settings from django.test.client import RequestFactory from django.utils.deprecation import RemovedInDjango20Warning from django.views.generic.base import View Loading Loading @@ -143,13 +143,24 @@ class CreateViewTests(TestCase): self.assertRedirects(res, 'http://testserver/edit/authors/create/') self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe>']) @ignore_warnings(category=RemovedInDjango20Warning) def test_create_with_interpolated_redirect(self): res = self.client.post('/edit/authors/create/interpolate_redirect/', {'name': 'Randall Munroe', 'slug': 'randall-munroe'}) res = self.client.post( '/edit/authors/create/interpolate_redirect/', {'name': 'Randall Munroe', 'slug': 'randall-munroe'} ) self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe>']) self.assertEqual(res.status_code, 302) pk = Author.objects.all()[0].pk pk = Author.objects.first().pk self.assertRedirects(res, 'http://testserver/edit/author/%d/update/' % pk) # Also test with escaped chars in URL res = self.client.post( '/edit/authors/create/interpolate_redirect_nonascii/', {'name': 'John Doe', 'slug': 'john-doe'} ) self.assertEqual(res.status_code, 302) pk = Author.objects.get(name='John Doe').pk self.assertRedirects(res, 'http://testserver/%C3%A9dit/author/{}/update/'.format(pk)) def test_create_with_special_properties(self): res = self.client.get('/edit/authors/create/special/') Loading Loading @@ -272,17 +283,28 @@ class UpdateViewTests(TestCase): self.assertRedirects(res, 'http://testserver/edit/authors/create/') self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (author of xkcd)>']) @ignore_warnings(category=RemovedInDjango20Warning) def test_update_with_interpolated_redirect(self): a = Author.objects.create( name='Randall Munroe', slug='randall-munroe', ) res = self.client.post('/edit/author/%d/update/interpolate_redirect/' % a.pk, {'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'}) res = self.client.post( '/edit/author/%d/update/interpolate_redirect/' % a.pk, {'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'} ) self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (author of xkcd)>']) self.assertEqual(res.status_code, 302) pk = Author.objects.all()[0].pk pk = Author.objects.first().pk self.assertRedirects(res, 'http://testserver/edit/author/%d/update/' % pk) # Also test with escaped chars in URL res = self.client.post( '/edit/author/%d/update/interpolate_redirect_nonascii/' % a.pk, {'name': 'John Doe', 'slug': 'john-doe'} ) self.assertEqual(res.status_code, 302) pk = Author.objects.get(name='John Doe').pk self.assertRedirects(res, 'http://testserver/%C3%A9dit/author/{}/update/'.format(pk)) def test_update_with_special_properties(self): a = Author.objects.create( Loading Loading @@ -368,12 +390,18 @@ class DeleteViewTests(TestCase): self.assertRedirects(res, 'http://testserver/edit/authors/create/') self.assertQuerysetEqual(Author.objects.all(), []) @ignore_warnings(category=RemovedInDjango20Warning) 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(), []) # Also test with escaped chars in URL a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'}) res = self.client.post('/edit/author/{}/delete/interpolate_redirect_nonascii/'.format(a.pk)) self.assertEqual(res.status_code, 302) self.assertRedirects(res, 'http://testserver/%C3%A9dit/authors/create/?deleted={}'.format(a.pk)) def test_delete_with_special_properties(self): a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'}) Loading Loading
django/views/generic/edit.py +19 −2 Original line number Diff line number Diff line import inspect import re import warnings from django.core.exceptions import ImproperlyConfigured Loading Loading @@ -162,7 +163,15 @@ class ModelFormMixin(FormMixin, SingleObjectMixin): Returns the supplied URL. """ if self.success_url: if re.search(r'%\([^\)]+\)', self.success_url): warnings.warn( "%()s placeholder style in success_url is deprecated. " "Please replace them by the {} Python format syntax.", RemovedInDjango20Warning, stacklevel=2 ) url = self.success_url % self.object.__dict__ else: url = self.success_url.format(**self.object.__dict__) else: try: url = self.object.get_absolute_url() Loading Loading @@ -288,7 +297,15 @@ class DeletionMixin(object): def get_success_url(self): if self.success_url: if re.search(r'%\([^\)]+\)', self.success_url): warnings.warn( "%()s placeholder style in success_url is deprecated. " "Please replace them by the {} Python format syntax.", RemovedInDjango20Warning, stacklevel=2 ) return self.success_url % self.object.__dict__ else: return self.success_url.format(**self.object.__dict__) else: raise ImproperlyConfigured( "No URL to redirect to. Provide a success_url.") Loading
docs/internals/deprecation.txt +3 −0 Original line number Diff line number Diff line Loading @@ -158,6 +158,9 @@ details on these changes. and ``Storage.save()`` to be defined without a ``max_length`` argument will be removed. * Support for the legacy ``%(<foo>)s`` syntax in ``ModelFormMixin.success_url`` will be removed. .. _deprecation-removed-in-1.9: 1.9 Loading
docs/ref/class-based-views/mixins-editing.txt +14 −2 Original line number Diff line number Diff line Loading @@ -160,9 +160,15 @@ ModelFormMixin ``success_url`` may contain dictionary string formatting, which will be interpolated against the object's field attributes. For example, you could use ``success_url="/polls/%(slug)s/"`` to example, you could use ``success_url="/polls/{slug}/"`` to redirect to a URL composed out of the ``slug`` field on a model. .. versionchanged:: 1.8 Support for the new brace-based Python formatting syntax has been added. The old ``%(slug)s`` placeholder syntax support has been deprecated and will be removed in Django 2.0. .. method:: get_form_class() Retrieve the form class to instantiate. If Loading Loading @@ -248,9 +254,15 @@ DeletionMixin ``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 could use ``success_url="/parent/{parent_id}/"`` to redirect to a URL composed out of the ``parent_id`` field on a model. .. versionchanged:: 1.8 Support for the new brace-based Python formatting syntax has been added. The old ``%(slug)s`` placeholder syntax support has been deprecated and will be removed in Django 2.0. .. method:: get_success_url() Returns the url to redirect to when the nominated object has been Loading
docs/releases/1.8.txt +12 −0 Original line number Diff line number Diff line Loading @@ -388,6 +388,11 @@ Generic Views require a ``form_class`` to be provided anymore. If not provided ``form_class`` defaults to :meth:`~django.views.generic.edit.FormMixin.get_form_class()`. * Placeholders in :attr:`ModelFormMixin.success_url <django.views.generic.edit.ModelFormMixin.success_url>` now support the Python :py:meth:`str.format()` syntax. The legacy ``%(<foo>)s`` syntax is still supported but will be removed in Django 2.0. Internationalization ^^^^^^^^^^^^^^^^^^^^ Loading Loading @@ -1550,6 +1555,13 @@ will be removed in Django 2.0. Using a single equals sign with the ``{% if %}`` template tag for equality testing was undocumented and untested. It's now deprecated in favor of ``==``. ``%(<foo>)s`` syntax in ``ModelFormMixin.success_url`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The legacy ``%(<foo>)s`` syntax in :attr:`ModelFormMixin.success_url <django.views.generic.edit.ModelFormMixin.success_url>` is deprecated and will be removed in Django 2.0. .. removed-features-1.8: Features removed in 1.8 Loading
tests/generic_views/test_edit.py +35 −7 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ import warnings from django.core.exceptions import ImproperlyConfigured from django.core.urlresolvers import reverse from django import forms from django.test import TestCase, override_settings from django.test import TestCase, ignore_warnings, override_settings from django.test.client import RequestFactory from django.utils.deprecation import RemovedInDjango20Warning from django.views.generic.base import View Loading Loading @@ -143,13 +143,24 @@ class CreateViewTests(TestCase): self.assertRedirects(res, 'http://testserver/edit/authors/create/') self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe>']) @ignore_warnings(category=RemovedInDjango20Warning) def test_create_with_interpolated_redirect(self): res = self.client.post('/edit/authors/create/interpolate_redirect/', {'name': 'Randall Munroe', 'slug': 'randall-munroe'}) res = self.client.post( '/edit/authors/create/interpolate_redirect/', {'name': 'Randall Munroe', 'slug': 'randall-munroe'} ) self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe>']) self.assertEqual(res.status_code, 302) pk = Author.objects.all()[0].pk pk = Author.objects.first().pk self.assertRedirects(res, 'http://testserver/edit/author/%d/update/' % pk) # Also test with escaped chars in URL res = self.client.post( '/edit/authors/create/interpolate_redirect_nonascii/', {'name': 'John Doe', 'slug': 'john-doe'} ) self.assertEqual(res.status_code, 302) pk = Author.objects.get(name='John Doe').pk self.assertRedirects(res, 'http://testserver/%C3%A9dit/author/{}/update/'.format(pk)) def test_create_with_special_properties(self): res = self.client.get('/edit/authors/create/special/') Loading Loading @@ -272,17 +283,28 @@ class UpdateViewTests(TestCase): self.assertRedirects(res, 'http://testserver/edit/authors/create/') self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (author of xkcd)>']) @ignore_warnings(category=RemovedInDjango20Warning) def test_update_with_interpolated_redirect(self): a = Author.objects.create( name='Randall Munroe', slug='randall-munroe', ) res = self.client.post('/edit/author/%d/update/interpolate_redirect/' % a.pk, {'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'}) res = self.client.post( '/edit/author/%d/update/interpolate_redirect/' % a.pk, {'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'} ) self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (author of xkcd)>']) self.assertEqual(res.status_code, 302) pk = Author.objects.all()[0].pk pk = Author.objects.first().pk self.assertRedirects(res, 'http://testserver/edit/author/%d/update/' % pk) # Also test with escaped chars in URL res = self.client.post( '/edit/author/%d/update/interpolate_redirect_nonascii/' % a.pk, {'name': 'John Doe', 'slug': 'john-doe'} ) self.assertEqual(res.status_code, 302) pk = Author.objects.get(name='John Doe').pk self.assertRedirects(res, 'http://testserver/%C3%A9dit/author/{}/update/'.format(pk)) def test_update_with_special_properties(self): a = Author.objects.create( Loading Loading @@ -368,12 +390,18 @@ class DeleteViewTests(TestCase): self.assertRedirects(res, 'http://testserver/edit/authors/create/') self.assertQuerysetEqual(Author.objects.all(), []) @ignore_warnings(category=RemovedInDjango20Warning) 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(), []) # Also test with escaped chars in URL a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'}) res = self.client.post('/edit/author/{}/delete/interpolate_redirect_nonascii/'.format(a.pk)) self.assertEqual(res.status_code, 302) self.assertRedirects(res, 'http://testserver/%C3%A9dit/authors/create/?deleted={}'.format(a.pk)) def test_delete_with_special_properties(self): a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'}) Loading