Drf-yasg: Custom SerializerInspector is not called

Created on 1 Jun 2018  路  8Comments  路  Source: axnsan12/drf-yasg

I am using a Serializer for request body initially, but I also want to add couple of more parameter into it, hence I wrote custom serializer inspector:

from drf_yasg.inspectors import SerializerInspector

class BaseFieldSerializerInspector(SerializerInspector):

    def get_request_parameters(self, serializer, in_):
        parameters = super().get_request_parameters(serializer, in_)
        # add extra parameters here
        return parameters

And used it like so:

@swagger_auto_schema(
    operation_description='Updates a field.',
    manual_parameters=[FIELD_ID_PATH_PARAMETER],
    request_body=BaseFieldSerializer,
    responses={
        status.HTTP_200_OK: openapi.Response(
            'Field updated successfully.',
            BaseFieldSerializer
        )
    },
    field_inspectors=[BaseFieldSerializerInspector]
)

But BaseFieldSerializerInspector is never called. Kindly help on this please. Thanks!

documentation question

Most helpful comment

Awesome! That worked. Thanks!

All 8 comments

get_request_parameters is only called when the serializer is converted to form parameters (i.e. formdata request body).

For convesion to schema object you have to override one of get_schema or add_manual_fields , or, alternatively, process_result.

You also have the option of overriding field_to_swagger_object to catch both Parameter and Schema generation (this method is also called interally from get_schema and get_request_parameters)

https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#parameterObject
https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaObject

Thanks for the response, some code example would be really helpful here. BaseFieldSerializer (as the name suggest its a base serializer for other field types) I would like to add some other fields manually in request_body which are not part of BaseFieldSerializer. e.g. I would like to add options field in request body with description saying Required if field_type is "enum"

Got it working:

class BaseFieldSerializerInspector(SerializerInspector):

    def process_result(self, result, method_name, obj, **kwargs):

        if isinstance(result, openapi.Schema.OR_REF):
            # traverse any references and alter the Schema object in place
            schema = openapi.resolve_ref(result, self.components)

            if schema.type == openapi.TYPE_OBJECT:
                schema.properties['test'] = openapi.Schema(
                    title='Test',
                    description='The test.',
                    type=openapi.TYPE_STRING,
                )

            # no ``return schema`` here, because it would mean we always generate
            # an inline `object` instead of a definition reference

        # return back the same object that we got - i.e. a reference if we got a reference
        return result

Thanks!

How to identify in process_result that openapi.TYPE_OBJECT is of request_body or responses?

@intellisense there is no difference! A SerializerInspector converts a serializer into a Schema object. The same Schema object is used in all places where this serializer is involved - request, response, nested inside another serializer, etc.

There is an issue tracking support for what you're asking (#70), however no one has provided any implementation for that and I'm not particularly fond of the idea (aka not going to implement it myself).

@axnsan12 Thanks for the clarification, one last help I need from you I would like to add options property which would be an array of objects, using the above approach in process_result:

schema.properties['options'] = openapi.Schema(
    title='Options',
    description='Array of objects',
    type=openapi.TYPE_ARRAY,
    items=openapi.Items(
        type=openapi.TYPE_OBJECT,
    )
)

There is already a serializer for options OptionsSerializer, is it possible to somehow use that serializer here for items? if not how can I further customize openapi.items to also include information regarding object type?:

items=openapi.Items(
    type=openapi.TYPE_OBJECT,  # I want to define properties for object here
)

Thanks for all the help.

You can use probe_field_inspectors:

options_schema = self.probe_field_inspectors(OptionsSerializer(many=True), openapi.Schema, True)

Awesome! That worked. Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tiltec picture tiltec  路  4Comments

Amoki picture Amoki  路  4Comments

phihag picture phihag  路  5Comments

hnykda picture hnykda  路  3Comments

therefromhere picture therefromhere  路  3Comments