1
0
mirror of https://github.com/django/django.git synced 2025-04-10 08:19:39 +00:00

Added request.parsers

This commit is contained in:
David Smith 2023-12-01 15:35:05 +00:00
parent 476501242c
commit 31aabb20c2
5 changed files with 81 additions and 4 deletions

View File

@ -19,6 +19,7 @@ from django.http import (
HttpResponseServerError,
QueryDict,
parse_cookie,
parsers,
)
from django.urls import set_script_prefix
from django.utils.functional import cached_property
@ -111,6 +112,10 @@ class ASGIRequest(HttpRequest):
self._stream = body_file
# Other bits.
self.resolver_match = None
self._parsers = [
parsers.FormParser(),
parsers.MultiPartParser(),
]
@cached_property
def GET(self):

View File

@ -3,7 +3,7 @@ from io import IOBase
from django.conf import settings
from django.core import signals
from django.core.handlers import base
from django.http import HttpRequest, QueryDict, parse_cookie
from django.http import HttpRequest, QueryDict, parse_cookie, parsers
from django.urls import set_script_prefix
from django.utils.encoding import repercent_broken_unicode
from django.utils.functional import cached_property
@ -78,6 +78,10 @@ class WSGIRequest(HttpRequest):
self._stream = LimitedStream(self.environ["wsgi.input"], content_length)
self._read_started = False
self.resolver_match = None
self._parsers = [
parsers.FormParser(),
parsers.MultiPartParser(),
]
def _get_scheme(self):
return self.environ.get("wsgi.url_scheme")

View File

@ -69,6 +69,10 @@ class HttpRequest:
self.resolver_match = None
self.content_type = None
self.content_params = None
self._parsers = [
parsers.FormParser(),
parsers.MultiPartParser(),
]
def __repr__(self):
if self.method is None or not self.get_full_path():
@ -417,6 +421,19 @@ class HttpRequest:
def readlines(self):
return list(self)
@property
def parsers(self):
return self._parsers
@parsers.setter
def parsers(self, parsers):
# TODO Also check for _data once added
if hasattr(self, "_files"):
raise AttributeError(
"You cannot change parsers after processing the request's content."
)
self._parsers = parsers
class HttpHeaders(CaseInsensitiveMapping):
HTTP_PREFIX = "HTTP_"

View File

@ -56,3 +56,20 @@ Parses HTML form content (). The ``parse()`` method returns a
Parses multipart form content and supports file uploads. The method returns
a ``QueryDict`` for ``data`` and an ``MultiValueDict`` for ``FILES``.
HttpRequest.Parsers
===================
``HttpRequest.parsers`` returns a list of parsers to be used when parsing a
request's content. By default, the parsers list will be Django's included
parsers (``FormParser, ``MultiPartParser``).
Parsers can be customised by setting a list of parsers to be used on the
request. This could be in a middleware or in a view, but must be done before
``data`` or ``FILES`` is accessed. For example:
.. code-block:: python
def index(request):
request.parsers = [MyCustomParser(), FormParser(), ...]
...

View File

@ -1,9 +1,12 @@
from unittest import TestCase
from django.core.handlers.wsgi import WSGIRequest
from django.http import HttpRequest
from django.http.parsers import BaseParser, FormParser, MultiPartParser
from django.test import SimpleTestCase
from django.test.client import FakePayload
from django.utils.http import urlencode
class TestParsers(TestCase):
class TestParsers(SimpleTestCase):
def test_can_handle(self):
parser = MultiPartParser()
self.assertIs(parser.can_handle("multipart/form-data"), True)
@ -25,3 +28,34 @@ class TestParsers(TestCase):
self.assertIs(parser.can_handle("application/json"), False)
self.assertTrue(parser.can_handle("text/*"), True)
self.assertTrue(parser.can_handle("text/csv"), True)
def test_request_parser_no_setting(self):
request = HttpRequest()
form, multipart = request.parsers
self.assertIsInstance(form, FormParser)
self.assertIsInstance(multipart, MultiPartParser)
def test_set_parser(self):
request = HttpRequest()
request.parsers = [FormParser()]
self.assertEqual(len(request.parsers), 1)
self.assertIsInstance(request.parsers[0], FormParser)
def test_set_parsers_following_files_access(self):
payload = FakePayload(urlencode({"key": "value"}))
request = WSGIRequest(
{
"REQUEST_METHOD": "POST",
"CONTENT_LENGTH": len(payload),
"CONTENT_TYPE": "application/x-www-form-urlencoded",
"wsgi.input": payload,
}
)
# can set parsers
request.parsers = []
# access files
request.FILES
msg = "You cannot change parsers after processing the request's content."
with self.assertRaisesMessage(AttributeError, msg):
request.parsers = []