python drf-spectacular:将OpenApiResponse添加到无序列化器的基于函数的视图

dm7nw8vv  于 2023-04-19  发布在  Python
关注(0)|答案(2)|浏览(233)

因此,我使用drf-spectacular记录以下代码:

from rest_framework import response
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from rest_framework.permissions import AllowAny
from rest_framework import status

from drf_spectacular.utils import extend_schema, OpenApiParameter

def passcode_generator:
    return 0 # placeholder

@extend_schema(
    parameters=[
        OpenApiParameter(name="callsign", required=True, type=str),
    ],
    description="Get an APRS-IS passcode for a given callsign",
)
@api_view(["POST"])
@permission_classes([AllowAny])
def get_passcode(request):
    callsign = request.data.get("callsign", None)
    if callsign is None:
        raise Response(
            {"error": "Missing callsign"}, status=status.HTTP_400_BAD_REQUEST
        )
    return Response({"passcode": passcode_generator(callsign)})

我不明白的是如何记录响应。也就是说,在drf_spectacular.utils中有OpenApiResponse,但文档非常少。我如何在这个系统中记录我的API的响应?

2hh7jdfx

2hh7jdfx1#

如果你没有Serializer,你可以使用inline_serializer

from drf_spectacular.utils import extend_schema, OpenApiParameter, inline_serializer

# ...

@extend_schema(
    parameters=[
        OpenApiParameter(name="callsign", required=True, type=str),
    ],
    description="Get an APRS-IS passcode for a given callsign",
    responses={
       200: inline_serializer(
           name='PasscodeResponse',
           fields={
               'passcode': serializers.CharField(),
           }
       ), 
       400: OpenApiResponse(description='Missing callsign'),
    }
)
@api_view(["POST"])
@permission_classes([AllowAny])
def get_passcode(request):
    callsign = request.data.get("callsign", None)
    # ...
lhcgjxsq

lhcgjxsq2#

与此同时,我发现了一个令人满意的答案,也让自动文档生成器感到高兴:
我创建了几个序列化器:

from rest_framework import serializers

class CallsignSerializer(serializers.Serializer):
    callsign = serializers.CharField(max_length=200)

class PasscodeSerializer(serializers.Serializer):
    passcode = serializers.CharField(max_length=200)

在视图中(注意最后一行之前的注解):

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import AllowAny

from drf_spectacular.utils import extend_schema

from aprs.api.serializers import CallsignSerializer, PasscodeSerializer
from aprs.vendor.passcode import passcode_generator

class PasscodeView(APIView):
    """
    View to get the APRS passcode from a callsign
    """

    permission_classes = [
        AllowAny,
    ]

    serializer_class = CallsignSerializer

    @extend_schema(responses=PasscodeSerializer)
    def post(self, request):
        """
        Get the APRS passcode from a callsign
        """
        serializer = CallsignSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        callsign = serializer.validated_data["callsign"]
        passcode = passcode_generator(callsign)

        passcode_serializer = PasscodeSerializer(data={"passcode": passcode})
        passcode_serializer.is_valid(raise_exception=True)

        # The serializer isn't passed here directly because otherwise DRF's browsable API
        # will create a POST form for the PasscodeSerializer, instead of the
        # CallsignSerializer. It is used in the lines above, instead of passing a
        # dictionary here directly as a form of validation.
        return Response(passcode_serializer.validated_data)

相关问题