#34063: request.POST not populated for multipart/form-data via AsyncClient
---------------------------------------------+------------------------
Reporter: Timo Ludwig | Owner: nobody
Type: Bug | Status: new
Component: Testing framework | Version: 4.0
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
---------------------------------------------+------------------------
In test cases with the `AsyncClient` and requests with the default content
type `"multipart/form-data"`, I cannot test views which access
`request.POST` before accessing `request.body`.
I'm very sorry if this is a duplicate of #32189 and this is the expected
behavior, but the way I understood it is that `request.POST` should be
populated for all form requests, so both `application/x-www-form-
urlencoded` and `multipart/form-data`, right?
If I just copy the
[https://github.com/django/django/blob/9b0c9821ed4dd9920cc7c5e7b657720d91a89bdc/tests/test_client/tests.py#L132-L140
test_post] case from the sync `ClientTest` (and adapt it to the async
structure as follows):
{{{
diff --git a/tests/test_client/tests.py b/tests/test_client/tests.py
index 57dc22ea0c..8cebaae9e7 100644
--- a/tests/test_client/tests.py
+++ b/tests/test_client/tests.py
@@ -1103,6 +1103,16 @@ class AsyncClientTest(TestCase):
response = await self.async_client.get("/get_view/", {"var":
"val"})
self.assertContains(response, "This is a test. val is the
value.")
+ async def test_post(self):
+ "POST some data to a view"
+ post_data = {"value": 37}
+ response = await self.async_client.post("/post_view/", post_data)
+
+ # Check some response details
+ self.assertContains(response, "Data received")
+ self.assertEqual(response.context["data"], "37")
+ self.assertEqual(response.templates[0].name, "POST Template")
+
@override_settings(ROOT_URLCONF="test_client.urls")
class AsyncRequestFactoryTest(SimpleTestCase):
}}}
the test case fails with:
{{{
FAIL: test_post (test_client.tests.AsyncClientTest)
POST some data to a view
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3.10/unittest/case.py", line 59, in
testPartExecutor
yield
File "/usr/lib/python3.10/unittest/case.py", line 591, in run
self._callTestMethod(testMethod)
File "/usr/lib/python3.10/unittest/case.py", line 549, in
_callTestMethod
method()
File "/home/user/.local/lib/python3.10/site-packages/asgiref/sync.py",
line 218, in __call__
return call_result.result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 451, in
result
return self.__get_result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in
__get_result
raise self._exception
File "/home/user/.local/lib/python3.10/site-packages/asgiref/sync.py",
line 284, in main_wrap
result = await self.awaitable(*args, **kwargs)
File "/home/django/tests/test_client/tests.py", line 1109, in test_post
response = await self.async_client.post("/post_view/", post_data)
File "/home/user/django/django/test/client.py", line 1072, in request
self.check_exception(response)
File "/home/user/django/django/test/client.py", line 666, in
check_exception
raise exc_value
File "/home/user/.local/lib/python3.10/site-packages/asgiref/sync.py",
line 472, in thread_handler
raise exc_info[1]
File "/home/user/django/django/core/handlers/exception.py", line 42, in
inner
response = await get_response(request)
File "/home/user/django/django/core/handlers/base.py", line 253, in
_get_response_async
response = await wrapped_callback(
File "/home/user/.local/lib/python3.10/site-packages/asgiref/sync.py",
line 435, in __call__
ret = await asyncio.wait_for(future, timeout=None)
File "/usr/lib/python3.10/asyncio/tasks.py", line 408, in wait_for
return await fut
File "/home/user/.local/lib/python3.10/site-
packages/asgiref/current_thread_executor.py", line 22, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/user/.local/lib/python3.10/site-packages/asgiref/sync.py",
line 476, in thread_handler
return func(*args, **kwargs)
File "/home/django/tests/test_client/views.py", line 83, in post_view
if request.POST:
File "/home/user/django/django/core/handlers/asgi.py", line 113, in
_get_post
self._load_post_and_files()
File "/home/user/django/django/http/request.py", line 386, in
_load_post_and_files
self._post, self._files = self.parse_file_upload(self.META, data)
File "/home/user/django/django/http/request.py", line 334, in
parse_file_upload
return parser.parse()
File "/home/user/django/django/http/multipartparser.py", line 165, in
parse
for item_type, meta_data, field_stream in Parser(stream,
self._boundary):
File "/home/user/django/django/http/multipartparser.py", line 703, in
__iter__
for sub_stream in boundarystream:
File "/home/user/django/django/http/multipartparser.py", line 533, in
__next__
return LazyStream(BoundaryIter(self._stream, self._boundary))
File "/home/user/django/django/http/multipartparser.py", line 560, in
__init__
unused_char = self._stream.read(1)
File "/home/user/django/django/http/multipartparser.py", line 427, in
read
return b"".join(parts())
File "/home/user/django/django/http/multipartparser.py", line 418, in
parts
chunk = next(self)
File "/home/user/django/django/http/multipartparser.py", line 440, in
__next__
output = next(self._producer)
File "/home/user/django/django/http/multipartparser.py", line 507, in
__next__
data = self.flo.read(self.chunk_size)
File "/home/user/django/django/http/request.py", line 421, in read
return self._stream.read(*args, **kwargs)
File "/home/user/django/django/test/client.py", line 82, in read
assert (
AssertionError: Cannot read more than the available bytes from the HTTP
incoming data.
}}}
While the same test case (and the same content type) succeeds for the sync
`Client`.
I would be willing to provide a patch if someone could point me in the
right direction.
--
Ticket URL: <https://code.djangoproject.com/ticket/34063>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/010701838a386409-2c5530a3-1542-4c4e-b0ba-adb255564c5d-000000%40eu-central-1.amazonses.com.