summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
Diffstat (limited to 'django')
-rw-r--r--django/test/client.py238
1 files changed, 231 insertions, 7 deletions
diff --git a/django/test/client.py b/django/test/client.py
index eed2d4f828..d44e30ff56 100644
--- a/django/test/client.py
+++ b/django/test/client.py
@@ -705,9 +705,6 @@ class AsyncRequestFactory(RequestFactory):
]
)
s["_body_file"] = FakePayload(data)
- follow = extra.pop("follow", None)
- if follow is not None:
- s["follow"] = follow
if query_string := extra.pop("QUERY_STRING", None):
s["query_string"] = query_string
if headers:
@@ -1296,10 +1293,6 @@ class AsyncClient(ClientMixin, AsyncRequestFactory):
query environment, which can be overridden using the arguments to the
request.
"""
- if "follow" in request:
- raise NotImplementedError(
- "AsyncClient request methods do not accept the follow parameter."
- )
scope = self._base_scope(**request)
# Curry a data dictionary into an instance of the template renderer
# callback function.
@@ -1338,3 +1331,234 @@ class AsyncClient(ClientMixin, AsyncRequestFactory):
if response.cookies:
self.cookies.update(response.cookies)
return response
+
+ async def get(
+ self,
+ path,
+ data=None,
+ follow=False,
+ secure=False,
+ *,
+ headers=None,
+ **extra,
+ ):
+ """Request a response from the server using GET."""
+ self.extra = extra
+ self.headers = headers
+ response = await super().get(
+ path, data=data, secure=secure, headers=headers, **extra
+ )
+ if follow:
+ response = await self._ahandle_redirects(
+ response, data=data, headers=headers, **extra
+ )
+ return response
+
+ async def post(
+ self,
+ path,
+ data=None,
+ content_type=MULTIPART_CONTENT,
+ follow=False,
+ secure=False,
+ *,
+ headers=None,
+ **extra,
+ ):
+ """Request a response from the server using POST."""
+ self.extra = extra
+ self.headers = headers
+ response = await super().post(
+ path,
+ data=data,
+ content_type=content_type,
+ secure=secure,
+ headers=headers,
+ **extra,
+ )
+ if follow:
+ response = await self._ahandle_redirects(
+ response, data=data, content_type=content_type, headers=headers, **extra
+ )
+ return response
+
+ async def head(
+ self,
+ path,
+ data=None,
+ follow=False,
+ secure=False,
+ *,
+ headers=None,
+ **extra,
+ ):
+ """Request a response from the server using HEAD."""
+ self.extra = extra
+ self.headers = headers
+ response = await super().head(
+ path, data=data, secure=secure, headers=headers, **extra
+ )
+ if follow:
+ response = await self._ahandle_redirects(
+ response, data=data, headers=headers, **extra
+ )
+ return response
+
+ async def options(
+ self,
+ path,
+ data="",
+ content_type="application/octet-stream",
+ follow=False,
+ secure=False,
+ *,
+ headers=None,
+ **extra,
+ ):
+ """Request a response from the server using OPTIONS."""
+ self.extra = extra
+ self.headers = headers
+ response = await super().options(
+ path,
+ data=data,
+ content_type=content_type,
+ secure=secure,
+ headers=headers,
+ **extra,
+ )
+ if follow:
+ response = await self._ahandle_redirects(
+ response, data=data, content_type=content_type, headers=headers, **extra
+ )
+ return response
+
+ async def put(
+ self,
+ path,
+ data="",
+ content_type="application/octet-stream",
+ follow=False,
+ secure=False,
+ *,
+ headers=None,
+ **extra,
+ ):
+ """Send a resource to the server using PUT."""
+ self.extra = extra
+ self.headers = headers
+ response = await super().put(
+ path,
+ data=data,
+ content_type=content_type,
+ secure=secure,
+ headers=headers,
+ **extra,
+ )
+ if follow:
+ response = await self._ahandle_redirects(
+ response, data=data, content_type=content_type, headers=headers, **extra
+ )
+ return response
+
+ async def patch(
+ self,
+ path,
+ data="",
+ content_type="application/octet-stream",
+ follow=False,
+ secure=False,
+ *,
+ headers=None,
+ **extra,
+ ):
+ """Send a resource to the server using PATCH."""
+ self.extra = extra
+ self.headers = headers
+ response = await super().patch(
+ path,
+ data=data,
+ content_type=content_type,
+ secure=secure,
+ headers=headers,
+ **extra,
+ )
+ if follow:
+ response = await self._ahandle_redirects(
+ response, data=data, content_type=content_type, headers=headers, **extra
+ )
+ return response
+
+ async def delete(
+ self,
+ path,
+ data="",
+ content_type="application/octet-stream",
+ follow=False,
+ secure=False,
+ *,
+ headers=None,
+ **extra,
+ ):
+ """Send a DELETE request to the server."""
+ self.extra = extra
+ self.headers = headers
+ response = await super().delete(
+ path,
+ data=data,
+ content_type=content_type,
+ secure=secure,
+ headers=headers,
+ **extra,
+ )
+ if follow:
+ response = await self._ahandle_redirects(
+ response, data=data, content_type=content_type, headers=headers, **extra
+ )
+ return response
+
+ async def trace(
+ self,
+ path,
+ data="",
+ follow=False,
+ secure=False,
+ *,
+ headers=None,
+ **extra,
+ ):
+ """Send a TRACE request to the server."""
+ self.extra = extra
+ self.headers = headers
+ response = await super().trace(
+ path, data=data, secure=secure, headers=headers, **extra
+ )
+ if follow:
+ response = await self._ahandle_redirects(
+ response, data=data, headers=headers, **extra
+ )
+ return response
+
+ async def _ahandle_redirects(
+ self,
+ response,
+ data="",
+ content_type="",
+ headers=None,
+ **extra,
+ ):
+ """
+ Follow any redirects by requesting responses from the server using GET.
+ """
+ response.redirect_chain = []
+ while response.status_code in REDIRECT_STATUS_CODES:
+ redirect_chain = response.redirect_chain
+ response = await self._follow_redirect(
+ response,
+ data=data,
+ content_type=content_type,
+ headers=headers,
+ **extra,
+ )
+ response.redirect_chain = redirect_chain
+ self._ensure_redirects_not_cyclic(response)
+ return response