Reputation: 1240
I use Django, the DRF, drf-yasg and Swagger Codegen to automatically build TypeScript code to access my REST API.
In the Django backend I added a path to be served with the DRF:
rest_router = routers.DefaultRouter()
rest_router.register(r'source/(?P<source_id>[0-9]+)/document', DocumentViewSet)
DocumentViewSet
is a DRF ModelViewSet.
As you can see, the source_id
parameter is of numeric type. However, the resulting generated API description defines the source_id
parameter as type String.
Obviously the numeric regexp in the path setting is not enough so I guess I need some type annotation in the DocumentViewSet
class? I tried the following code, but this showed no effect:
@swagger_auto_schema(
manual_parameters=[
openapi.Parameter(name="source_id",
required=True,
type="integer",
in_="path",
description="Source reference",
),
],
)
class DocumentViewSet(viewsets.ModelViewSet):
serializer_class = rest_serializers.DocumentSerializer
queryset = models.Document.objects.all().order_by('id')
How can I tell drf-yasg to set the source_id
parameter to type Integer?
Upvotes: 5
Views: 4886
Reputation: 123
This may be something made easier in a newer version of drf_yasf, but I managed to get it working with something similar to the following way:
from django.utils.decorators import method_decorator
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework import viewsets
params = [
openapi.Parameter("source_id",
openapi.IN_PATH,
description="Source reference",
type=openapi.TYPE_INTEGER
)
]
@method_decorator(name="list", decorator=swagger_auto_schema(manual_parameters=params))
@method_decorator(name="create", decorator=swagger_auto_schema(manual_parameters=params))
@method_decorator(name="retrieve", decorator=swagger_auto_schema(manual_parameters=params))
@method_decorator(name="update", decorator=swagger_auto_schema(manual_parameters=params))
@method_decorator(name="partial_update", decorator=swagger_auto_schema(manual_parameters=params))
@method_decorator(name="destroy", decorator=swagger_auto_schema(manual_parameters=params))
class DocumentViewSet(viewsets.ModelViewSet):
serializer_class = rest_serializers.DocumentSerializer
queryset = models.Document.objects.all().order_by('id')
I have here decorated all base ViewSet actions but you could decorate only the ones you need, you can also decorate your custom actions (no need to use method_decorator in that case: you can directly decorate the action with @swagger_auto_schema). Note that you could also decorate the base actions with @swagger_auto_schema directly if you were to override them in your class.
Upvotes: 0
Reputation: 477
The standard OpenAPISchemaGenerator on drf-yasg only checks if the path variable name matches with the view queryset model field, and uses the type of the model field if such exists. Otherwise it defaults to string. Your original code should work if the Document model has a numeric field named "source_id". Foreign relations should work as well, but it's very much possible that in that case your parameter name should be the name of the field (source) and not the id reference (source_id).
@swagger_auto_schema should be applied on the view method or methods, not the view class. AFAIK applying it to view class does nothing. See https://drf-yasg.readthedocs.io/en/stable/custom_spec.html#the-swagger-auto-schema-decorator
As a side quest I poked around a bit to see if it's possible to determine the type using pythons built-in typing, and the short answer is yes, but it's a bit messy. Throwing this out in case anyone finds it useful, use it with your own risk.
class CustomSchemaGenerator(OpenAPISchemaGenerator):
def get_path_parameters(self, path, view_cls):
parameters = super().get_path_parameters(path, view_cls)
for p in parameters:
if p.in_ == openapi.IN_PATH and p.type == openapi.TYPE_STRING:
p.type = getattr(view_cls, f'path_type_{p.name}', openapi.TYPE_STRING)
return parameters
In the above generator, we allow drf-yasg to do the initial type determination, but then add an extra step that allows overriding type in the view class.
Example view
class DocumentView(APIView):
path_type_source_id = openapi.TYPE_INTEGER
Enable the generator with SWAGGER_SETTINGS
SWAGGER_SETTINGS = {
'DEFAULT_GENERATOR_CLASS': 'path.to.CustomSchemaGenerator',
}
Upvotes: 0