Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

drf-spectacular: Add OpenApiResponse to a serializer-less function-based view

So, I'm documenting the following piece of code using 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)})

What I can't understand how to do is how to document the responses. Namely, there is OpenApiResponse in drf_spectacular.utils but the documentation is very slim. How can I document the responses of my API with this system?

like image 745
Rui Oliveira Avatar asked Oct 15 '25 11:10

Rui Oliveira


2 Answers

If you don't have a Serializer, you can use 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)
    # ...
like image 191
Yevgeniy Kosmak Avatar answered Oct 18 '25 01:10

Yevgeniy Kosmak


It is possible to set OpenAPI schema without using Serializers and operating only with dicts:

from rest_framework.views import APIView
from drf_spectacular.utils import extend_schema

view_schema = {
    'description': 'Some login view',
    'auth': None,
    'request': {
        "application/json": {
            "description": "User credentials",
            "type": "object",
            "properties": {
                "username": {
                    "type": "string",
                    "minLength": 1
                },
                "password": {
                    "type": "string",
                    "minLength": 1
                }
            },
            "required": [
                "username",
                "password"
            ]
        }
    },
    'responses': {
        (200, "application/json"): {
            "description": "Success",
            "type": "object",
            "properties": {
                "access_token": {
                    "type": "string",
                    "minLength": 1
                },
                "refresh_token": {
                    "type": "string",
                    "minLength": 1
                }
            },
            "required": [
                "access_token",
                "refresh_token"
            ]
        },
        (401, "application/json"): {
            "description": "Login failure",
            "type": "object",
            "properties": {
                "status": {
                    "type": "number"
                },
                "error": {
                    "type": "string"
                }
            },
            "required": [
                "status"
            ]
        }
    }
}

class LoginView(APIView):

    @extend_schema(**view_schema)
    def post(self, request: Request):
        ...
like image 43
rzlvmp Avatar answered Oct 18 '25 01:10

rzlvmp