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

OpenAPI Schema generation fails with generic APIViews #1066

Open
1 of 2 tasks
qianxuanyon opened this issue Jun 1, 2022 · 3 comments
Open
1 of 2 tasks

OpenAPI Schema generation fails with generic APIViews #1066

qianxuanyon opened this issue Jun 1, 2022 · 3 comments
Labels

Comments

@qianxuanyon
Copy link

qianxuanyon commented Jun 1, 2022

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

  • 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
@qianxuanyon qianxuanyon added the bug label Jun 1, 2022
@sliverc
Copy link
Member

sliverc commented Jun 1, 2022

Could you provide the full stacktrace of the error? Thanks.

@qianxuanyon
Copy link
Author

[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

@sliverc sliverc changed the title and the APIView in rest_framework cannot coexist OpenAPI Schema generation fails with generic APIViews Jun 29, 2022
@sliverc
Copy link
Member

sliverc commented Jun 29, 2022

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants