diff options
Diffstat (limited to 'rest_framework/request.py')
| -rw-r--r-- | rest_framework/request.py | 59 |
1 files changed, 55 insertions, 4 deletions
diff --git a/rest_framework/request.py b/rest_framework/request.py index 27532661..d7e74674 100644 --- a/rest_framework/request.py +++ b/rest_framework/request.py @@ -4,7 +4,7 @@ The Request class is used as a wrapper around the standard request object. The wrapped request then offers a richer API, in particular : - content automatically parsed according to `Content-Type` header, - and available as `request.DATA` + and available as `request.data` - full support of PUT method, including support for file uploads - form overloading of HTTP method, content type and content """ @@ -13,10 +13,12 @@ from django.conf import settings from django.http import QueryDict from django.http.multipartparser import parse_header from django.utils.datastructures import MultiValueDict +from django.utils.datastructures import MergeDict as DjangoMergeDict from rest_framework import HTTP_HEADER_ENCODING from rest_framework import exceptions from rest_framework.compat import BytesIO from rest_framework.settings import api_settings +import warnings def is_form_media_type(media_type): @@ -58,6 +60,15 @@ class override_method(object): self.view.action = self.action +class MergeDict(DjangoMergeDict, dict): + """ + Using this as a workaround until the parsers API is properly + addressed in 3.1. + """ + def __init__(self, *dicts): + self.dicts = dicts + + class Empty(object): """ Placeholder for unset attributes. @@ -82,6 +93,7 @@ def clone_request(request, method): parser_context=request.parser_context) ret._data = request._data ret._files = request._files + ret._full_data = request._full_data ret._content_type = request._content_type ret._stream = request._stream ret._method = method @@ -91,6 +103,10 @@ def clone_request(request, method): ret._auth = request._auth if hasattr(request, '_authenticator'): ret._authenticator = request._authenticator + if hasattr(request, 'accepted_renderer'): + ret.accepted_renderer = request.accepted_renderer + if hasattr(request, 'accepted_media_type'): + ret.accepted_media_type = request.accepted_media_type return ret @@ -133,6 +149,7 @@ class Request(object): self.parser_context = parser_context self._data = Empty self._files = Empty + self._full_data = Empty self._method = Empty self._content_type = Empty self._stream = Empty @@ -186,13 +203,31 @@ class Request(object): return self._stream @property - def QUERY_PARAMS(self): + def query_params(self): """ More semantically correct name for request.GET. """ return self._request.GET @property + def QUERY_PARAMS(self): + """ + Synonym for `.query_params`, for backwards compatibility. + """ + warnings.warn( + "`request.QUERY_PARAMS` is pending deprecation. Use `request.query_params` instead.", + PendingDeprecationWarning, + stacklevel=1 + ) + return self._request.GET + + @property + def data(self): + if not _hasattr(self, '_full_data'): + self._load_data_and_files() + return self._full_data + + @property def DATA(self): """ Parses the request body and returns the data. @@ -200,6 +235,11 @@ class Request(object): Similar to usual behaviour of `request.POST`, except that it handles arbitrary parsers, and also works on methods other than POST (eg PUT). """ + warnings.warn( + "`request.DATA` is pending deprecation. Use `request.data` instead.", + PendingDeprecationWarning, + stacklevel=1 + ) if not _hasattr(self, '_data'): self._load_data_and_files() return self._data @@ -212,6 +252,11 @@ class Request(object): Similar to usual behaviour of `request.FILES`, except that it handles arbitrary parsers, and also works on methods other than POST (eg PUT). """ + warnings.warn( + "`request.FILES` is pending deprecation. Use `request.data` instead.", + PendingDeprecationWarning, + stacklevel=1 + ) if not _hasattr(self, '_files'): self._load_data_and_files() return self._files @@ -265,13 +310,17 @@ class Request(object): def _load_data_and_files(self): """ - Parses the request content into self.DATA and self.FILES. + Parses the request content into `self.data`. """ if not _hasattr(self, '_content_type'): self._load_method_and_content_type() if not _hasattr(self, '_data'): self._data, self._files = self._parse() + if self._files: + self._full_data = MergeDict(self._data, self._files) + else: + self._full_data = self._data def _load_method_and_content_type(self): """ @@ -333,6 +382,7 @@ class Request(object): # At this point we're committed to parsing the request as form data. self._data = self._request.POST self._files = self._request.FILES + self._full_data = MergeDict(self._data, self._files) # Method overloading - change the method and remove the param from the content. if ( @@ -350,7 +400,7 @@ class Request(object): ): self._content_type = self._data[self._CONTENTTYPE_PARAM] self._stream = BytesIO(self._data[self._CONTENT_PARAM].encode(self.parser_context['encoding'])) - self._data, self._files = (Empty, Empty) + self._data, self._files, self._full_data = (Empty, Empty, Empty) def _parse(self): """ @@ -380,6 +430,7 @@ class Request(object): # logging the request or similar. self._data = QueryDict('', encoding=self._request._encoding) self._files = MultiValueDict() + self._full_data = self._data raise # Parser classes may return the raw data, or a |
