Search code examples
djangodjango-rest-frameworkdrf-spectacular

Is there an alternative to using a serializer for drf-spectacular's extend_schema request param?


I'm using drf-spectacular to generate swagger/redoc API documentation.

One of the most useful features is the ability to test requests via the generated swagger html page, but I'd like to enforce the application/x-www-form-urlencoded content-type so that when the request is received by my Django endpoints, the request.data has the encoded data instead of it ending up as part of a query string. drf-spectacular always seems to default to query strings e.g. /objects/action/?key=value

The only way I've figured out how to do this is to use a serializer in conjunction with the request content-type e.g.

@extend_schema(
    request={'application/x-www-form-urlencoded': DoTheActionInputsSerializer},
    responses={200: DoTheActionOutputsSerializer},
    methods=["POST"]
)
@action(methods=['post'], detail=False)
def do_the_action(self, request, *args, **kwargs):
    ...

This works great, but it does require a lot of small serializers that may only have one or two attributes. Is there an alternative way of achieving this inside the extend_schema decorator?

I was hoping something like the following would work, but doesn't

request={'application/x-www-form-urlencoded': {'schema': {'foo_id': OpenApiTypes.INT}}},

Solution

  • I think the documentation answers that question. You can use inline_serializer for those small one-off cases. It allows you to do this:

        @extend_schema(responses={
            '2XX': SimpleSerializer,
            '401': inline_serializer('Error1', fields={'detail': serializers.CharField()}),
        })
    

    This works the same for @extend_schema(request=inline_serializer(...))

    As a matter of last resort, you can also put a raw schema dict into request or response.

    Note: If you want application/x-www-form-urlencoded to be detected automatically, just do

    @action(methods=['post'], detail=False, parser_classes=[parsers.FormParser])