From 8b9fec1ae40f0883b2fe86e56de1b1ea52d686c4 Mon Sep 17 00:00:00 2001 From: Tommy Beadle Date: Wed, 21 Aug 2024 17:12:37 -0400 Subject: [PATCH 1/3] Support the adrf action "alist" when determining if a view is a listing view. --- drf_spectacular/openapi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drf_spectacular/openapi.py b/drf_spectacular/openapi.py index ff0e5e36..ead7220b 100644 --- a/drf_spectacular/openapi.py +++ b/drf_spectacular/openapi.py @@ -144,7 +144,7 @@ def _is_list_view(self, serializer: Optional[_SerializerType] = None) -> bool: if is_basic_type(serializer): return False if hasattr(self.view, 'action'): - return self.view.action == 'list' + return self.view.action in ('list', 'alist') # list responses are "usually" only returned by GET if self.method != 'GET': return False From ce341aa82cc302f5893b86c2a0fcf7a252a9e181 Mon Sep 17 00:00:00 2001 From: Tommy Beadle Date: Thu, 12 Sep 2024 12:11:09 -0400 Subject: [PATCH 2/3] Support async view methods in extend_schema_view. --- drf_spectacular/drainage.py | 19 ++++++++++++++----- drf_spectacular/openapi.py | 7 +++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/drf_spectacular/drainage.py b/drf_spectacular/drainage.py index 7c44890b..9ad0ea56 100644 --- a/drf_spectacular/drainage.py +++ b/drf_spectacular/drainage.py @@ -182,8 +182,12 @@ def get_view_method_names(view, schema=None) -> List[str]: return [ item for item in dir(view) if callable(getattr(view, item, None)) and ( item in view.http_method_names - or item in schema.method_mapping.values() - or item == 'list' + or ( + item in schema.async_method_mapping.values() + if view.view_is_async + else item in schema.method_mapping.values() + ) + or item == ('alist' if view.view_is_async else 'list') or hasattr(getattr(view, item, None), 'mapping') ) ] @@ -202,9 +206,14 @@ def isolate_view_method(view, method_name): if method_name in view.__dict__ and method.__name__ != 'handler': return method - @functools.wraps(method) - def wrapped_method(self, request, *args, **kwargs): - return method(self, request, *args, **kwargs) + if getattr(view, "view_is_async", False): + @functools.wraps(method) + async def wrapped_method(self, request, *args, **kwargs): + return await method(self, request, *args, **kwargs) + else: + @functools.wraps(method) + def wrapped_method(self, request, *args, **kwargs): + return method(self, request, *args, **kwargs) # wraps() will only create a shallow copy of method.__dict__. Updates to "kwargs" # via @extend_schema would leak to the original method. Isolate by creating a copy. diff --git a/drf_spectacular/openapi.py b/drf_spectacular/openapi.py index ead7220b..77042e68 100644 --- a/drf_spectacular/openapi.py +++ b/drf_spectacular/openapi.py @@ -57,6 +57,13 @@ class AutoSchema(ViewInspector): 'patch': 'partial_update', 'delete': 'destroy', } + async_method_mapping = { + 'get': 'aretrieve', + 'post': 'acreate', + 'put': 'aupdate', + 'patch': 'partial_aupdate', + 'delete': 'adestroy', + } def get_operation( self, From 67d9f952b4384b5c06cc2421a2a18499c1fc9ba8 Mon Sep 17 00:00:00 2001 From: Tommy Beadle Date: Thu, 31 Oct 2024 08:30:03 -0400 Subject: [PATCH 3/3] Support older versions of Django. --- drf_spectacular/drainage.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drf_spectacular/drainage.py b/drf_spectacular/drainage.py index 9ad0ea56..5a6f75bf 100644 --- a/drf_spectacular/drainage.py +++ b/drf_spectacular/drainage.py @@ -184,10 +184,10 @@ def get_view_method_names(view, schema=None) -> List[str]: item in view.http_method_names or ( item in schema.async_method_mapping.values() - if view.view_is_async + if getattr(view, "view_is_async", False) else item in schema.method_mapping.values() ) - or item == ('alist' if view.view_is_async else 'list') + or item == ('alist' if getattr(view, "view_is_async", False) else 'list') or hasattr(getattr(view, item, None), 'mapping') ) ]