0
votes

I was recently integrated into projects that are using the Django rest framework and swagger. I had to define a custom field for a serializer at some point and it works fine, but swagger doesn't recognize its type (it always marks it as string).

Custom field:

class InheritableAttribute(serializers.ReadOnlyField):
    def __init__(self, attribute_name, serializer_class=None):
        super().__init__()
        self.attribute_name = attribute_name
        self.serializer_class = serializer_class

    def get_attribute(self, instance):
        value = getattr(instance, self.attribute_name)
        if not value:
            value = getattr(instance.product, self.attribute_name)
        return value

    def to_representation(self, value):
        if self.serializer_class:
            return self.serializer_class(value).to_representation(value)
        return super().to_representation(value)

Serializer (simplified):

class Serializer:

    base_price = InheritableAttribute('base_price')
    keep_inventory_count = InheritableAttribute('keep_inventory_count')

Swagger:

swagger output

Here, I want base_price to be float and keep_inventory_count to be bool, for example.

Also, you may have noticed that the custom field is reused for different types of data, so the type should somehow be a parameter, but I can probably figure that stuff out; I just need to know how to set the type for a custom field so that swagger shows it correctly.

1
No there are no properties that can do that, swagger uses serializer or model Field type to open API field type mapping to show the field type. - Tarun Kumar

1 Answers

0
votes

No there are no properties that can do that, swagger uses serializer or model Field type to open API field type mapping. But if you want to achieve that then you can use the following approach then swagger can recognise correct field type based on what field class you have passed. See the following example:

class InheritableAttribute:

    @staticmethod
    def create(attribute_name, serializer_field_class=None):
        serializer_field_class = serializers.ReadOnlyField if not serializers.ReadOnlyField else serializer_field_class

        class InstanceInheritableAttribute(serializer_field_class):
            def __init__(self, **kwargs):
                kwargs['read_only'] = True
                self.attribute_name = attribute_name
                super().__init__(**kwargs)

            def get_attribute(self, instance):
                value = getattr(instance, self.attribute_name)
                if not value:
                    value = getattr(instance.product, self.attribute_name)
                return value

            def to_representation(self, value):
                return super().to_representation(value)
        return InstanceInheritableAttribute()


class Serializer(serializers.Serializer):

    base_price = InheritableAttribute.create("base_price", serializers.FloatField)
    keep_inventory_count = InheritableAttribute.create("keep_inventory_count", serializers.BooleanField)