-2π
β
In the meanwhile, I found out a satisfying answer that also keeps automatic documentation generators happy:
I created a couple serializers:
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)
And in the views (notice the comment before the last line):
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)
π€Rui Oliveira
8π
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)
# ...
π€Yevgeniy Kosmak
0π
It is possible to set OpenAPI
schema without using Serializer
s and operating only with dict
s:
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):
...
π€rzlvmp
Source:stackexchange.com