在 django-rest-framework 和 swagger 中定义列表参数的正确方法
背景
我有以下视图,附带的 swagger UI 是由 django-spectaulous 生成的:
class AllowedNameType(Enum):
BRAND = "BRAND"
....
@classmethod
def list(cls):
return list(map(lambda c: c.value, cls))
class GenerateCompanyNamesViewSet(viewsets.ViewSet):
http_method_names = ["get"]
def list(self, request: Request, *args, **kwargs) -> Response:
"""Generate suggested company names"""
# query_params: dict = {}
allowed_name_types: list[AllowedNameType] = query_params.get("allowed_name_types")
suggestions: list[Suggestion] = ...
return Response(serializers.SuggestionSerializer(suggestions).data)
我想实现以下目标:
- swagger UI 应该有一个参数
allowed_name_types
,它是AllowedNameType< 的列表/code> 值
- 应根据序列化器定义对输入进行验证
- 应对 query_params 执行类型检查,以确保
allowed_name_types
的类型list[AllowedNameType]
(理想情况下,allowed_name_types
实际上是一个命名参数(例如list(..., allowed_name_types: list[AllowedNameType])
尝试解决方案
class AllowedNameTypesParamSerializer(rest_framework_serializers.Serializer):
allowed_name_types = rest_framework_serializers.ListField(
child=rest_framework_serializers.ChoiceField(choices=models.AllowedNameType.list()),
required=False,
allow_empty=True,
)
并将以下装饰器添加到列表方法中:
@extend_schema(
parameters=[
OpenApiParameter(name="allowed_name_types", required=True, type=AllowedNameTypesParamSerializer),
],
responses=serializers.FoodSearchAutoCompleteSerializer,
)
def list(....)
不幸的是:
- swagger 组件需要一个
{"allowed_name_types 字典:...}
而不是列表, - 列表元素的
allowed_name_types
验证不起作用(即我可以在列表中放置一个不是来自AllowedNameType的值) - 奇怪的是,调用
request.query_params.get('allowed_name_types')
仅返回 allowed_name_types 中的最后一个值。
帮助?
我确信我已经拥有了实现我想要的目标的所有拼图,但我不知道如何将它们拼凑在一起,以提供我所追求的记录良好的 API 和类型化验证的行为。任何帮助将不胜感激:)
Background
I have the following view and the accompanying swagger UI is generated by django-spectacular:
class AllowedNameType(Enum):
BRAND = "BRAND"
....
@classmethod
def list(cls):
return list(map(lambda c: c.value, cls))
class GenerateCompanyNamesViewSet(viewsets.ViewSet):
http_method_names = ["get"]
def list(self, request: Request, *args, **kwargs) -> Response:
"""Generate suggested company names"""
# query_params: dict = {}
allowed_name_types: list[AllowedNameType] = query_params.get("allowed_name_types")
suggestions: list[Suggestion] = ...
return Response(serializers.SuggestionSerializer(suggestions).data)
I want to achieve the following:
- The swagger UI should have a parameter
allowed_name_types
which is a list ofAllowedNameType
values - The input should be validated as per the serializer definition
- Type checking should be enforced on query_params to make sure the
allowed_name_types
is of typelist[AllowedNameType]
(ideally,allowed_name_types
would actually be a named parameter in (eglist(..., allowed_name_types: list[AllowedNameType])
Attempted Solution
class AllowedNameTypesParamSerializer(rest_framework_serializers.Serializer):
allowed_name_types = rest_framework_serializers.ListField(
child=rest_framework_serializers.ChoiceField(choices=models.AllowedNameType.list()),
required=False,
allow_empty=True,
)
and added the following decorator to the list method:
@extend_schema(
parameters=[
OpenApiParameter(name="allowed_name_types", required=True, type=AllowedNameTypesParamSerializer),
],
responses=serializers.FoodSearchAutoCompleteSerializer,
)
def list(....)
This leads to the following interface:
Unfortunately:
- The swagger component expects a dictionary of
{"allowed_name_types:...}
instead of a list - the
allowed_name_types
validation of list elements does not work (i.e I can put a value in the list that is not from AllowedNameType) - Strangely, calling
request.query_params.get('allowed_name_types')
only returns the last value from the allowed_name_types.
Help?
I'm sure I have all the pieces of the jigsaw to achieve what I want, but I cannot figure out how to piece them together to give me the well documented API and typed validated behaviour that I'm after. Any help would be much appreciated :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论