在 drf-yasg OpenAPI 和 Swagger 视图中显示 SlugRelatedField 的可能值(选择)
Display possible values (choices) of SlugRelatedField in drf-yasg OpenAPI and Swagger views
我有几个模型用作枚举(基本上,模型只是一个名称和一个 slug),比如货币和国家等,我试图在 drf-yasg 中显示可用的选项但没有成功.
我最后一次尝试是将其添加到序列化程序的 Meta class:
swagger_schema_fields = {
'currency': {'enum': list(Currency.objects.values_list('slug', flat=True))}
}
当然,它失败得很惨——不仅没有显示枚举值,还破坏了序列化程序(因为它使用的是字符串而不是实际模型)。
有什么办法吗?
最后,我添加了一个新字段 class,它完全符合我的需要。我不能保证这是解决这个问题的最有效方法(检索 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
我有几个模型用作枚举(基本上,模型只是一个名称和一个 slug),比如货币和国家等,我试图在 drf-yasg 中显示可用的选项但没有成功. 我最后一次尝试是将其添加到序列化程序的 Meta class:
swagger_schema_fields = {
'currency': {'enum': list(Currency.objects.values_list('slug', flat=True))}
}
当然,它失败得很惨——不仅没有显示枚举值,还破坏了序列化程序(因为它使用的是字符串而不是实际模型)。
有什么办法吗?
最后,我添加了一个新字段 class,它完全符合我的需要。我不能保证这是解决这个问题的最有效方法(检索 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