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!
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!
Most helpful comment
Awesome! That worked. Thanks!