Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #18659 -- Deprecated request.REQUEST and MergeDict

Thanks Aymeric Augustin for the suggestion.
  • Loading branch information...
commit 2fb5a51fa3ac276efc7121ec9de91f092a986104 1 parent 98788d3
@Bouke Bouke authored timgraham committed
View
12 django/contrib/admin/options.py
@@ -1284,8 +1284,10 @@ def add_view(self, request, form_url='', extra_context=None):
context = dict(self.admin_site.each_context(),
title=_('Add %s') % force_text(opts.verbose_name),
adminform=adminForm,
- is_popup=IS_POPUP_VAR in request.REQUEST,
- to_field=request.REQUEST.get(TO_FIELD_VAR),
+ is_popup=(IS_POPUP_VAR in request.POST or
+ IS_POPUP_VAR in request.GET),
+ to_field=request.POST.get(TO_FIELD_VAR,
+ request.GET.get(TO_FIELD_VAR)),
media=media,
inline_admin_formsets=inline_admin_formsets,
errors=helpers.AdminErrorList(form, formsets),
@@ -1357,8 +1359,10 @@ def change_view(self, request, object_id, form_url='', extra_context=None):
adminform=adminForm,
object_id=object_id,
original=obj,
- is_popup=IS_POPUP_VAR in request.REQUEST,
- to_field=request.REQUEST.get(TO_FIELD_VAR),
+ is_popup=(IS_POPUP_VAR in request.POST or
+ IS_POPUP_VAR in request.GET),
+ to_field=request.POST.get(TO_FIELD_VAR,
+ request.GET.get(TO_FIELD_VAR)),
media=media,
inline_admin_formsets=inline_admin_formsets,
errors=helpers.AdminErrorList(form, formsets),
View
3  django/contrib/auth/admin.py
@@ -144,7 +144,8 @@ def user_change_password(self, request, id, form_url=''):
'adminForm': adminForm,
'form_url': form_url,
'form': form,
- 'is_popup': IS_POPUP_VAR in request.REQUEST,
+ 'is_popup': (IS_POPUP_VAR in request.POST or
+ IS_POPUP_VAR in request.GET),
'add': True,
'change': False,
'has_delete_permission': False,
View
1  django/contrib/auth/tests/test_views.py
@@ -526,7 +526,6 @@ def test_login_csrf_rotate(self, password='password'):
req.COOKIES[settings.CSRF_COOKIE_NAME] = token1
req.method = "POST"
req.POST = {'username': 'testclient', 'password': password, 'csrfmiddlewaretoken': token1}
- req.REQUEST = req.POST
# Use POST request to log in
SessionMiddleware().process_request(req)
View
9 django/contrib/auth/views.py
@@ -28,7 +28,8 @@ def login(request, template_name='registration/login.html',
"""
Displays the login form and handles the login action.
"""
- redirect_to = request.REQUEST.get(redirect_field_name, '')
+ redirect_to = request.POST.get(redirect_field_name,
+ request.GET.get(redirect_field_name, ''))
if request.method == "POST":
form = authentication_form(request, data=request.POST)
@@ -71,8 +72,10 @@ def logout(request, next_page=None,
if next_page is not None:
next_page = resolve_url(next_page)
- if redirect_field_name in request.REQUEST:
- next_page = request.REQUEST[redirect_field_name]
+ if (redirect_field_name in request.POST or
+ redirect_field_name in request.GET):
+ next_page = request.POST.get(redirect_field_name,
+ request.GET.get(redirect_field_name))
# Security check -- don't allow redirection to a different host.
if not is_safe_url(url=next_page, host=request.get_host()):
next_page = request.path
View
3  django/core/handlers/wsgi.py
@@ -5,6 +5,7 @@
import sys
from io import BytesIO
from threading import Lock
+import warnings
from django import http
from django.conf import settings
@@ -129,6 +130,8 @@ def _parse_content_type(self, ctype):
return content_type, content_params
def _get_request(self):
+ warnings.warn('`request.REQUEST` is deprecated, use `request.GET` or '
+ '`request.POST` instead.', PendingDeprecationWarning, 2)
if not hasattr(self, '_request'):
self._request = datastructures.MergeDict(self.POST, self.GET)
return self._request
View
2  django/utils/datastructures.py
@@ -12,6 +12,8 @@ class MergeDict(object):
first occurrence will be used.
"""
def __init__(self, *dicts):
+ warnings.warn('`MergeDict` is deprecated, use `dict.update()` '
+ 'instead.', PendingDeprecationWarning, 2)
self.dicts = dicts
def __bool__(self):
View
2  django/views/i18n.py
@@ -24,7 +24,7 @@ def set_language(request):
redirect to the page in the request (the 'next' parameter) without changing
any state.
"""
- next = request.REQUEST.get('next')
+ next = request.POST.get('next', request.GET.get('next'))
if not is_safe_url(url=next, host=request.get_host()):
next = request.META.get('HTTP_REFERER')
if not is_safe_url(url=next, host=request.get_host()):
View
4 docs/internals/deprecation.txt
@@ -469,6 +469,10 @@ these changes.
* ``django.forms.get_declared_fields`` will be removed.
+* The ``WSGIRequest.REQUEST`` property will be removed.
+
+* The class ``django.utils.datastructures.MergeDict`` will be removed.
+
2.0
---
View
3  docs/ref/request-response.txt
@@ -110,6 +110,9 @@ All attributes should be considered read-only, unless stated otherwise below.
.. attribute:: HttpRequest.REQUEST
+ .. deprecated:: 1.7
+ Use the more explicit ``GET`` and ``POST`` instead.
+
For convenience, a dictionary-like object that searches ``POST`` first,
then ``GET``. Inspired by PHP's ``$_REQUEST``.
View
15 docs/releases/1.7.txt
@@ -639,3 +639,18 @@ deprecated. Use :djadminopt:`--natural-foreign` instead.
Similarly, the ``use_natural_keys`` argument for ``serializers.serialize()``
has been deprecated. Use ``use_natural_foreign_keys`` instead.
+
+Merging of ``POST`` and ``GET`` arguments into ``WSGIRequest.REQUEST``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It was already strongly suggested that you use ``GET`` and ``POST`` instead of
+``REQUEST``, because the former are more explicit. The property ``REQUEST`` is
+deprecated and will be removed in Django 1.9.
+
+``django.utils.datastructures.MergeDict`` class
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``MergeDict`` exists primarily to support merging ``POST`` and ``GET``
+arguments into a ``REQUEST`` property on ``WSGIRequest``. To merge
+dictionaries, use ``dict.update()`` instead. The class ``MergeDict`` is
+deprecated and will be removed in Django 1.9.
View
22 tests/deprecation/tests.py
@@ -1,8 +1,9 @@
from __future__ import unicode_literals
import warnings
-from django.test import SimpleTestCase
+from django.test import SimpleTestCase, RequestFactory
from django.utils import six
+from django.utils.datastructures import MergeDict
from django.utils.deprecation import RenameMethodsBase
@@ -156,3 +157,22 @@ class Deprecated(DeprecatedMixin, RenamedMixin, Renamed):
'`DeprecatedMixin.old` is deprecated, use `new` instead.',
'`RenamedMixin.old` is deprecated, use `new` instead.',
])
+
+
+class DeprecatingRequestMergeDictTest(SimpleTestCase):
+ def test_deprecated_request(self):
+ """
+ Ensure the correct warning is raised when WSGIRequest.REQUEST is
+ accessed.
+ """
+ with warnings.catch_warnings(record=True) as recorded:
+ warnings.simplefilter('always')
+ request = RequestFactory().get('/')
+ _ = request.REQUEST
+
+ msgs = [str(warning.message) for warning in recorded]
+ self.assertEqual(msgs, [
+ '`request.REQUEST` is deprecated, use `request.GET` or '
+ '`request.POST` instead.',
+ '`MergeDict` is deprecated, use `dict.update()` instead.',
+ ])
View
10 tests/forms_tests/tests/test_forms.py
@@ -3,6 +3,7 @@
import copy
import datetime
+import warnings
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.validators import RegexValidator
@@ -560,9 +561,12 @@ class SongForm(Form):
f = SongForm(data)
self.assertEqual(f.errors, {})
- data = MergeDict(MultiValueDict(dict(name=['Yesterday'], composers=['J', 'P'])))
- f = SongForm(data)
- self.assertEqual(f.errors, {})
+ # MergeDict is deprecated, but is supported until removed.
+ with warnings.catch_warnings(record=True):
+ warnings.simplefilter("always")
+ data = MergeDict(MultiValueDict(dict(name=['Yesterday'], composers=['J', 'P'])))
+ f = SongForm(data)
+ self.assertEqual(f.errors, {})
def test_multiple_hidden(self):
class SongForm(Form):
View
20 tests/test_client_regress/views.py
@@ -1,4 +1,5 @@
import json
+import warnings
from django.conf import settings
from django.contrib.auth.decorators import login_required
@@ -32,13 +33,20 @@ def get_view(request):
def request_data(request, template='base.html', data='sausage'):
"A simple view that returns the request data in the context"
+
+ # request.REQUEST is deprecated, but needs testing until removed.
+ with warnings.catch_warnings(record=True) as w:
+ warnings.simplefilter("always")
+ request_foo = request.REQUEST.get('foo')
+ request_bar = request.REQUEST.get('bar')
+
return render_to_response(template, {
- 'get-foo':request.GET.get('foo',None),
- 'get-bar':request.GET.get('bar',None),
- 'post-foo':request.POST.get('foo',None),
- 'post-bar':request.POST.get('bar',None),
- 'request-foo':request.REQUEST.get('foo',None),
- 'request-bar':request.REQUEST.get('bar',None),
+ 'get-foo': request.GET.get('foo'),
+ 'get-bar': request.GET.get('bar'),
+ 'post-foo': request.POST.get('foo'),
+ 'post-bar': request.POST.get('bar'),
+ 'request-foo': request_foo,
+ 'request-bar': request_bar,
'data': data,
})
View
2  tests/utils_tests/test_datastructures.py
@@ -136,7 +136,7 @@ def test_reversed(self):
self.assertEqual(list(reversed(self.d2)), [7, 0, 9, 1])
-class MergeDictTests(SimpleTestCase):
+class MergeDictTests(IgnorePendingDeprecationWarningsMixin, SimpleTestCase):
def test_simple_mergedict(self):
d1 = {'chris':'cool', 'camri':'cute', 'cotton':'adorable',
Please sign in to comment.
Something went wrong with that request. Please try again.