#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 django-updates+unsubscr...@googlegroups.com. 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.