sanic-org / sanic-ext

Extended Sanic functionality
https://sanic.dev/en/plugins/sanic-ext/getting-started.html
MIT License
50 stars 36 forks source link

[Bug] The OpenAPI document generated by RESTful API does not work properly. #261

Open jsonvot opened 2 months ago

jsonvot commented 2 months ago

Describe the bug When I implement the RESTFuel-style API using the mixin method, I cannot obtain the expected OpenAPI document. The display is abnormal, and unexpected results other than medical ones occur when clicked.

Screenshots This is the display effect.

image image image image

To Reproduce

from sanic import Sanic
from sanic.blueprints import Blueprint
from sanic.views import HTTPMethodView

class CreateModelMixin:
    async def create(self, request, *args, **kwargs):
        ...

    async def post(self, request, *args, **kwargs):
        await self.create(request, *args, **kwargs)

class ListModelMixin:
    async def list(self, request, *args, **kwargs):
        ...

    async def get(self, request, *args, **kwargs):
        return await self.list(request, *args, **kwargs)

class UpdateModelMixin:
    async def update(self, request, *args, **kwargs):
        ...

    async def put(self, request, *args, **kwargs):
        return await self.update(request, *args, **kwargs)

class PartialUpdateModelMixin:
    async def partial_update(self, request, *args, **kwargs):
        ...

    async def patch(self, request, *args, **kwargs):
        return await self.partial_update(request, *args, **kwargs)

class DestroyModelMixin:
    async def destroy(self, request, *args, **kwargs):
        ...

    async def delete(self, request, *args, **kwargs):
        return await self.destroy(request, *args, **kwargs)

class RetrieveModelMixin:
    async def retrieve(self, request, *args, **kwargs):
        ...

    async def get(self, request, *args, **kwargs):
        return await self.retrieve(request, *args, **kwargs)

class GenericViewSet(HTTPMethodView):
    ...

class UserView(
    CreateModelMixin,
    ListModelMixin,
    GenericViewSet
):
    ...

class HomeView(
    CreateModelMixin,
    ListModelMixin,
    GenericViewSet
):
    ...

app = Sanic(__name__)
app.config.update(dict(
    OAS_URL_PREFIX='/docs',
    OAS_UI_DEFAULT='swagger',
    SWAGGER_UI_CONFIGURATION={
        "docExpansion": "list"
    },
    OAS_UI_SWAGGER_VERSION='5.0.0',
))
user_bp = Blueprint('user', url_prefix='/user')
home_bp = Blueprint('home', url_prefix='/home')
# admin_bp = Blueprint('admin', url_prefix='/admin')

user_bp.add_route(UserView.as_view(), '/info/<pk:int>/')
home_bp.add_route(HomeView.as_view(), '/info')

app.blueprint([
    user_bp,
    home_bp,
    # admin_bp
])

Expected behavior Hope that the RESTful API implemented using mixins can be displayed normally, routes can be displayed correctly, and the openapi swagger document that meets expectations can be generated correctly.Hope that the RESTful API implemented using mixins can be displayed normally, routes can be displayed correctly, and the openapi swagger document that meets expectations can be generated correctly.

Environment (please complete the following information):

Additional context Through my own investigation, I found that this problem is actually related to the view_class of the view class and mixin classes. Once a mixin class is inherited, the memory pointers in other view classes are the same. After I made changes to several locations in the file, it can work normally.

sanic_ext/utils/route.py

image

sanic_ext/extensions/openapi/blueprint.py

image image