Fixed #21587 -- Added a warning for changing default of RedirectView.permanent.

This commit is contained in:
Berker Peksag 2014-11-21 18:55:58 +02:00 committed by Tim Graham
parent d43dd03ca3
commit 9a30acad8a
7 changed files with 135 additions and 21 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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):

View File

@ -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')