Fixed #21587 -- Added a warning for changing default of RedirectView.permanent.
This commit is contained in:
parent
d43dd03ca3
commit
9a30acad8a
|
@ -1,6 +1,7 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import warnings
|
||||||
from functools import update_wrapper
|
from functools import update_wrapper
|
||||||
|
|
||||||
from django import http
|
from django import http
|
||||||
|
@ -8,8 +9,10 @@ from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.core.urlresolvers import reverse, NoReverseMatch
|
from django.core.urlresolvers import reverse, NoReverseMatch
|
||||||
from django.template.response import TemplateResponse
|
from django.template.response import TemplateResponse
|
||||||
from django.utils.decorators import classonlymethod
|
from django.utils.decorators import classonlymethod
|
||||||
|
from django.utils.deprecation import RemovedInDjango19Warning
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
|
||||||
|
_sentinel = object()
|
||||||
logger = logging.getLogger('django.request')
|
logger = logging.getLogger('django.request')
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,7 +51,6 @@ class View(object):
|
||||||
"""
|
"""
|
||||||
Main entry point for a request-response process.
|
Main entry point for a request-response process.
|
||||||
"""
|
"""
|
||||||
# sanitize keyword arguments
|
|
||||||
for key in initkwargs:
|
for key in initkwargs:
|
||||||
if key in cls.http_method_names:
|
if key in cls.http_method_names:
|
||||||
raise TypeError("You tried to pass in the %s method name as a "
|
raise TypeError("You tried to pass in the %s method name as a "
|
||||||
|
@ -159,11 +161,23 @@ class RedirectView(View):
|
||||||
"""
|
"""
|
||||||
A view that provides a redirect on any GET request.
|
A view that provides a redirect on any GET request.
|
||||||
"""
|
"""
|
||||||
permanent = True
|
permanent = _sentinel
|
||||||
url = None
|
url = None
|
||||||
pattern_name = None
|
pattern_name = None
|
||||||
query_string = False
|
query_string = False
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
if 'permanent' not in kwargs and self.permanent is _sentinel:
|
||||||
|
warnings.warn(
|
||||||
|
"Default value of 'RedirectView.permanent' will change "
|
||||||
|
"from True to False in Django 1.9. Set an explicit value "
|
||||||
|
"to silence this warning.",
|
||||||
|
RemovedInDjango19Warning,
|
||||||
|
stacklevel=3
|
||||||
|
)
|
||||||
|
self.permanent = True
|
||||||
|
super(RedirectView, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def get_redirect_url(self, *args, **kwargs):
|
def get_redirect_url(self, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Return the URL redirect to. Keyword arguments from the
|
Return the URL redirect to. Keyword arguments from the
|
||||||
|
|
|
@ -214,6 +214,10 @@ details on these changes.
|
||||||
* The `cache_choices` option to :class:`~django.forms.ModelChoiceField` and
|
* The `cache_choices` option to :class:`~django.forms.ModelChoiceField` and
|
||||||
:class:`~django.forms.ModelMultipleChoiceField` will be removed.
|
:class:`~django.forms.ModelMultipleChoiceField` will be removed.
|
||||||
|
|
||||||
|
* The default value of the
|
||||||
|
:attr:`RedirectView.permanent <django.views.generic.base.RedirectView.permanent>`
|
||||||
|
attribute will change from ``True`` to ``False``.
|
||||||
|
|
||||||
.. _deprecation-removed-in-1.8:
|
.. _deprecation-removed-in-1.8:
|
||||||
|
|
||||||
1.8
|
1.8
|
||||||
|
|
|
@ -222,6 +222,11 @@ RedirectView
|
||||||
status code 301. If ``False``, then the redirect will use status code
|
status code 301. If ``False``, then the redirect will use status code
|
||||||
302. By default, ``permanent`` is ``True``.
|
302. By default, ``permanent`` is ``True``.
|
||||||
|
|
||||||
|
.. deprecated:: 1.8
|
||||||
|
|
||||||
|
The default value of the ``permanent`` attribute will change from
|
||||||
|
``True`` to ``False`` in Django 1.9.
|
||||||
|
|
||||||
.. attribute:: query_string
|
.. attribute:: query_string
|
||||||
|
|
||||||
Whether to pass along the GET query string to the new location. If
|
Whether to pass along the GET query string to the new location. If
|
||||||
|
|
|
@ -1097,6 +1097,13 @@ deprecated: you should rename your ``qn`` arguments to ``compiler``, and call
|
||||||
``compiler.quote_name_unless_alias(...)`` where you previously called
|
``compiler.quote_name_unless_alias(...)`` where you previously called
|
||||||
``qn(...)``.
|
``qn(...)``.
|
||||||
|
|
||||||
|
Default value of ``RedirectView.permanent``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The default value of the
|
||||||
|
:attr:`RedirectView.permanent <django.views.generic.base.RedirectView.permanent>`
|
||||||
|
attribute will change from ``True`` to ``False`` in Django 1.9.
|
||||||
|
|
||||||
.. removed-features-1.8:
|
.. removed-features-1.8:
|
||||||
|
|
||||||
Features removed in 1.8
|
Features removed in 1.8
|
||||||
|
|
|
@ -2,10 +2,14 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
import time
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
|
import warnings
|
||||||
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
from django.utils import six
|
||||||
|
from django.utils.deprecation import RemovedInDjango19Warning
|
||||||
from django.test import TestCase, RequestFactory, override_settings
|
from django.test import TestCase, RequestFactory, override_settings
|
||||||
|
from django.test.utils import IgnoreDeprecationWarningsMixin
|
||||||
from django.views.generic import View, TemplateView, RedirectView
|
from django.views.generic import View, TemplateView, RedirectView
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
@ -328,7 +332,7 @@ class TemplateViewTest(TestCase):
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ROOT_URLCONF='generic_views.urls')
|
@override_settings(ROOT_URLCONF='generic_views.urls')
|
||||||
class RedirectViewTest(TestCase):
|
class RedirectViewTest(IgnoreDeprecationWarningsMixin, TestCase):
|
||||||
|
|
||||||
rf = RequestFactory()
|
rf = RequestFactory()
|
||||||
|
|
||||||
|
@ -440,6 +444,69 @@ class RedirectViewTest(TestCase):
|
||||||
self.assertEqual(response.status_code, 410)
|
self.assertEqual(response.status_code, 410)
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(ROOT_URLCONF='generic_views.urls')
|
||||||
|
class RedirectViewDeprecationTest(TestCase):
|
||||||
|
|
||||||
|
rf = RequestFactory()
|
||||||
|
|
||||||
|
def test_deprecation_warning_init(self):
|
||||||
|
with warnings.catch_warnings(record=True) as warns:
|
||||||
|
warnings.simplefilter('always')
|
||||||
|
|
||||||
|
view = RedirectView()
|
||||||
|
response = view.dispatch(self.rf.head('/python/'))
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 410)
|
||||||
|
self.assertEqual(len(warns), 1)
|
||||||
|
self.assertIs(warns[0].category, RemovedInDjango19Warning)
|
||||||
|
self.assertEqual(
|
||||||
|
six.text_type(warns[0].message),
|
||||||
|
"Default value of 'RedirectView.permanent' will change "
|
||||||
|
"from True to False in Django 1.9. Set an explicit value "
|
||||||
|
"to silence this warning.",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_deprecation_warning_raised_when_permanent_not_passed(self):
|
||||||
|
with warnings.catch_warnings(record=True) as warns:
|
||||||
|
warnings.simplefilter('always')
|
||||||
|
|
||||||
|
view_function = RedirectView.as_view(url='/bbb/')
|
||||||
|
request = self.rf.request(PATH_INFO='/aaa/')
|
||||||
|
view_function(request)
|
||||||
|
|
||||||
|
self.assertEqual(len(warns), 1)
|
||||||
|
self.assertIs(warns[0].category, RemovedInDjango19Warning)
|
||||||
|
self.assertEqual(
|
||||||
|
six.text_type(warns[0].message),
|
||||||
|
"Default value of 'RedirectView.permanent' will change "
|
||||||
|
"from True to False in Django 1.9. Set an explicit value "
|
||||||
|
"to silence this warning.",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_no_deprecation_warning_when_permanent_passed(self):
|
||||||
|
with warnings.catch_warnings(record=True) as warns:
|
||||||
|
warnings.simplefilter('always')
|
||||||
|
|
||||||
|
view_function = RedirectView.as_view(url='/bar/', permanent=False)
|
||||||
|
request = self.rf.request(PATH_INFO='/foo/')
|
||||||
|
view_function(request)
|
||||||
|
|
||||||
|
self.assertEqual(len(warns), 0)
|
||||||
|
|
||||||
|
def test_no_deprecation_warning_with_custom_redirectview(self):
|
||||||
|
class CustomRedirectView(RedirectView):
|
||||||
|
permanent = False
|
||||||
|
|
||||||
|
with warnings.catch_warnings(record=True) as warns:
|
||||||
|
warnings.simplefilter('always')
|
||||||
|
|
||||||
|
view_function = CustomRedirectView.as_view(url='/eggs/')
|
||||||
|
request = self.rf.request(PATH_INFO='/spam/')
|
||||||
|
view_function(request)
|
||||||
|
|
||||||
|
self.assertEqual(len(warns), 0)
|
||||||
|
|
||||||
|
|
||||||
class GetContextDataTest(unittest.TestCase):
|
class GetContextDataTest(unittest.TestCase):
|
||||||
|
|
||||||
def test_get_context_data_super(self):
|
def test_get_context_data_super(self):
|
||||||
|
|
|
@ -22,8 +22,11 @@ rather than the HTML rendered to the end-user.
|
||||||
"""
|
"""
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import warnings
|
||||||
|
|
||||||
from django.core import mail
|
from django.core import mail
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
from django.utils.deprecation import RemovedInDjango19Warning
|
||||||
from django.test import Client, TestCase, RequestFactory
|
from django.test import Client, TestCase, RequestFactory
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
|
|
||||||
|
@ -174,14 +177,18 @@ class ClientTest(TestCase):
|
||||||
|
|
||||||
def test_permanent_redirect(self):
|
def test_permanent_redirect(self):
|
||||||
"GET a URL that redirects permanently elsewhere"
|
"GET a URL that redirects permanently elsewhere"
|
||||||
response = self.client.get('/permanent_redirect_view/')
|
with warnings.catch_warnings():
|
||||||
# Check that the response was a 301 (permanent redirect)
|
warnings.simplefilter("ignore", RemovedInDjango19Warning)
|
||||||
self.assertRedirects(response, 'http://testserver/get_view/', status_code=301)
|
response = self.client.get('/permanent_redirect_view/')
|
||||||
|
# Check that the response was a 301 (permanent redirect)
|
||||||
|
self.assertRedirects(response, 'http://testserver/get_view/', status_code=301)
|
||||||
|
|
||||||
client_providing_host = Client(HTTP_HOST='django.testserver')
|
with warnings.catch_warnings():
|
||||||
response = client_providing_host.get('/permanent_redirect_view/')
|
warnings.simplefilter("ignore", RemovedInDjango19Warning)
|
||||||
# Check that the response was a 301 (permanent redirect) with absolute URI
|
client_providing_host = Client(HTTP_HOST='django.testserver')
|
||||||
self.assertRedirects(response, 'http://django.testserver/get_view/', status_code=301)
|
response = client_providing_host.get('/permanent_redirect_view/')
|
||||||
|
# Check that the response was a 301 (permanent redirect) with absolute URI
|
||||||
|
self.assertRedirects(response, 'http://django.testserver/get_view/', status_code=301)
|
||||||
|
|
||||||
def test_temporary_redirect(self):
|
def test_temporary_redirect(self):
|
||||||
"GET a URL that does a non-permanent redirect"
|
"GET a URL that does a non-permanent redirect"
|
||||||
|
@ -191,26 +198,34 @@ class ClientTest(TestCase):
|
||||||
|
|
||||||
def test_redirect_to_strange_location(self):
|
def test_redirect_to_strange_location(self):
|
||||||
"GET a URL that redirects to a non-200 page"
|
"GET a URL that redirects to a non-200 page"
|
||||||
response = self.client.get('/double_redirect_view/')
|
with warnings.catch_warnings():
|
||||||
|
warnings.simplefilter("ignore", RemovedInDjango19Warning)
|
||||||
|
response = self.client.get('/double_redirect_view/')
|
||||||
|
|
||||||
# Check that the response was a 302, and that
|
# Check that the response was a 302, and that
|
||||||
# the attempt to get the redirection location returned 301 when retrieved
|
# the attempt to get the redirection location returned 301 when retrieved
|
||||||
self.assertRedirects(response, 'http://testserver/permanent_redirect_view/', target_status_code=301)
|
self.assertRedirects(response, 'http://testserver/permanent_redirect_view/', target_status_code=301)
|
||||||
|
|
||||||
def test_follow_redirect(self):
|
def test_follow_redirect(self):
|
||||||
"A URL that redirects can be followed to termination."
|
"A URL that redirects can be followed to termination."
|
||||||
response = self.client.get('/double_redirect_view/', follow=True)
|
with warnings.catch_warnings():
|
||||||
self.assertRedirects(response, 'http://testserver/get_view/', status_code=302, target_status_code=200)
|
warnings.simplefilter("ignore", RemovedInDjango19Warning)
|
||||||
|
response = self.client.get('/double_redirect_view/', follow=True)
|
||||||
|
self.assertRedirects(response, 'http://testserver/get_view/', status_code=302, target_status_code=200)
|
||||||
self.assertEqual(len(response.redirect_chain), 2)
|
self.assertEqual(len(response.redirect_chain), 2)
|
||||||
|
|
||||||
def test_redirect_http(self):
|
def test_redirect_http(self):
|
||||||
"GET a URL that redirects to an http URI"
|
"GET a URL that redirects to an http URI"
|
||||||
response = self.client.get('/http_redirect_view/', follow=True)
|
with warnings.catch_warnings():
|
||||||
|
warnings.simplefilter("ignore", RemovedInDjango19Warning)
|
||||||
|
response = self.client.get('/http_redirect_view/', follow=True)
|
||||||
self.assertFalse(response.test_was_secure_request)
|
self.assertFalse(response.test_was_secure_request)
|
||||||
|
|
||||||
def test_redirect_https(self):
|
def test_redirect_https(self):
|
||||||
"GET a URL that redirects to an https URI"
|
"GET a URL that redirects to an https URI"
|
||||||
response = self.client.get('/https_redirect_view/', follow=True)
|
with warnings.catch_warnings():
|
||||||
|
warnings.simplefilter("ignore", RemovedInDjango19Warning)
|
||||||
|
response = self.client.get('/https_redirect_view/', follow=True)
|
||||||
self.assertTrue(response.test_was_secure_request)
|
self.assertTrue(response.test_was_secure_request)
|
||||||
|
|
||||||
def test_notfound_response(self):
|
def test_notfound_response(self):
|
||||||
|
|
|
@ -18,7 +18,7 @@ from django.http import HttpRequest, HttpResponseRedirect, HttpResponsePermanent
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.test import TestCase, override_settings
|
from django.test import TestCase, override_settings
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from django.utils.deprecation import RemovedInDjango20Warning
|
from django.utils.deprecation import RemovedInDjango19Warning, RemovedInDjango20Warning
|
||||||
|
|
||||||
from admin_scripts.tests import AdminScriptTestCase
|
from admin_scripts.tests import AdminScriptTestCase
|
||||||
|
|
||||||
|
@ -309,8 +309,10 @@ class ResolverTests(unittest.TestCase):
|
||||||
class ReverseLazyTest(TestCase):
|
class ReverseLazyTest(TestCase):
|
||||||
|
|
||||||
def test_redirect_with_lazy_reverse(self):
|
def test_redirect_with_lazy_reverse(self):
|
||||||
response = self.client.get('/redirect/')
|
with warnings.catch_warnings():
|
||||||
self.assertRedirects(response, "/redirected_to/", status_code=301)
|
warnings.simplefilter("ignore", RemovedInDjango19Warning)
|
||||||
|
response = self.client.get('/redirect/')
|
||||||
|
self.assertRedirects(response, "/redirected_to/", status_code=301)
|
||||||
|
|
||||||
def test_user_permission_with_lazy_reverse(self):
|
def test_user_permission_with_lazy_reverse(self):
|
||||||
User.objects.create_user('alfred', 'alfred@example.com', password='testpw')
|
User.objects.create_user('alfred', 'alfred@example.com', password='testpw')
|
||||||
|
|
Loading…
Reference in New Issue