django-rest-framework-json-api
django-rest-framework-json-api copied to clipboard
OpenAPI Schema generation fails with generic APIViews
Description of the Bug Report
class LogoutView(APIView):
pass
Errors when accessing documents
AttributeError: 'LogoutView' object has no attribute 'get_serializer'
Is fault tolerance possible when the program has api in other formats
Checklist
- [x] Certain that this is a bug (if unsure or you have a question use discussions instead)
- [ ] Code snippet or unit test added to reproduce bug
Could you provide the full stacktrace of the error? Thanks.
[01/Jun/2022 09:26:01] "GET /redoc/ HTTP/1.1" 200 625
Internal Server Error: /openapi
Traceback (most recent call last):
File "/Users/lidaoran/opt/anaconda3/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/Users/lidaoran/opt/anaconda3/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/lidaoran/opt/anaconda3/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/lidaoran/opt/anaconda3/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/lidaoran/opt/anaconda3/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/Users/lidaoran/opt/anaconda3/lib/python3.9/site-packages/rest_framework/schemas/views.py", line 48, in handle_exception
return super().handle_exception(exc)
File "/Users/lidaoran/opt/anaconda3/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/Users/lidaoran/opt/anaconda3/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/Users/lidaoran/opt/anaconda3/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/lidaoran/opt/anaconda3/lib/python3.9/site-packages/rest_framework/schemas/views.py", line 37, in get
schema = self.schema_generator.get_schema(request, self.public)
File "/Users/lidaoran/dev/django-rest-framework-json-api/rest_framework_json_api/schemas/openapi.py", line 266, in get_schema
schema = super().get_schema(request, public)
File "/Users/lidaoran/opt/anaconda3/lib/python3.9/site-packages/rest_framework/schemas/openapi.py", line 81, in get_schema
operation = view.schema.get_operation(path, method)
File "/Users/lidaoran/dev/django-rest-framework-json-api/rest_framework_json_api/schemas/openapi.py", line 429, in get_operation
self._add_get_collection_response(operation)
File "/Users/lidaoran/dev/django-rest-framework-json-api/rest_framework_json_api/schemas/openapi.py", line 494, in _add_get_collection_response
"200": self._get_toplevel_200_response(operation, collection=True)
File "/Users/lidaoran/dev/django-rest-framework-json-api/rest_framework_json_api/schemas/openapi.py", line 518, in _get_toplevel_200_response
"items": self._get_reference(self.view.get_serializer()),
AttributeError: 'LogoutView' object has no attribute 'get_serializer'
This is my configuration
urls.py
urlpatterns = [
path(
"openapi",
get_schema_view(
title="Example API",
description="API for all things …",
version="1.0.0",
generator_class=SchemaGenerator,
),
name="openapi-schema",
),
path('redoc/', TemplateView.as_view(
template_name='redoc.html',
extra_context={'schema_url':'openapi-schema'}
), name='redoc'),
]
This is the source code of the object reporting the error
class LogoutView(APIView):
"""
Calls Django logout method and delete the Token object
assigned to the current User object.
Accepts/Returns nothing.
"""
permission_classes = (AllowAny,)
throttle_scope = 'dj_rest_auth'
def get(self, request, *args, **kwargs):
if getattr(settings, 'ACCOUNT_LOGOUT_ON_GET', False):
response = self.logout(request)
else:
response = self.http_method_not_allowed(request, *args, **kwargs)
return self.finalize_response(request, response, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.logout(request)
def logout(self, request):
try:
request.user.auth_token.delete()
except (AttributeError, ObjectDoesNotExist):
pass
if getattr(settings, 'REST_SESSION_LOGIN', True):
django_logout(request)
response = Response(
{'detail': _('Successfully logged out.')},
status=status.HTTP_200_OK,
)
return response
Thanks for the additional information. So this seems to be an issue with our openapi implementation. As far as I see does the DRF implementation skip views without serializers.
We need to go through our openapi.py and all view.get_serializer()
call need to be changed to either self.get_request_serializer
or self.get_response_serializer
. If None is returned, that view will need to be ignored.
Any PR is welcome.