Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support the adrf action "alist" when determining if a view is a listing view. #1278

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions drf_spectacular/drainage.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)) 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), 'mapping')
)
]
Expand All @@ -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.
Expand Down
9 changes: 8 additions & 1 deletion drf_spectacular/openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -144,7 +151,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
Expand Down