首页 > 解决方案 > 在 drf-yasg OpenAPI 和 Swagger 视图中显示 SlugRelatedField 的可能值(选择)

问题描述

我有几个用作枚举的模型(基本上,模型只是一个名称和一个蛞蝓),如货币和国家等,我试图在 drf-yasg 中显示可用的选择但没有成功。我最后一次尝试是将它添加到序列化程序的 Meta 类中:

swagger_schema_fields = {
    'currency': {'enum': list(Currency.objects.values_list('slug', flat=True))}
}

但是当然它失败了——它不仅没有显示枚举值,而且还破坏了序列化程序(因为它使用字符串而不是实际模型)。

有没有办法做到这一点?

标签: djangodjango-rest-frameworkswaggerdrf-yasg

解决方案


最终,我添加了一个新的字段类,它完全符合我的需要。我不能保证这是解决这个问题的最有效方法(检索 swagger 页面似乎需要更长的时间),但它可以完成工作:

# choices_slug_field.py

from drf_yasg.inspectors import RelatedFieldInspector
from rest_framework.metadata import SimpleMetadata
from rest_framework.relations import SlugRelatedField
from rest_framework.serializers import ManyRelatedField, RelatedField


class ShowChoicesMetadata(SimpleMetadata):
    def get_field_info(self, field):
        field_info = super().get_field_info(field)
        if (not field_info.get('read_only') and
                isinstance(field, (ManyRelatedField, RelatedField)) and
                hasattr(field, 'choices') and
                getattr(field, 'show_choices', False)):
            field_info['choices'] = [
                {
                    'value': choice_value,
                    'display_name': str(choice_name)
                }
                for choice_value, choice_name in field.choices.items()
            ]

        return field_info


class ShowChoicesMixin:
    show_choices = True


class ChoicesSlugRelatedField(ShowChoicesMixin, SlugRelatedField):
    pass


class ShowChoicesFieldInspector(RelatedFieldInspector):
    def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs):
        dataobj = super().field_to_swagger_object(field, swagger_object_type, use_references, **kwargs)
        if (isinstance(field, ChoicesSlugRelatedField) and hasattr(field, 'choices')
                and getattr(field, 'show_choices', False) and 'enum' not in dataobj):
            dataobj['enum'] = [k for k, v in field.choices.items()]
        return dataobj

推荐阅读