在 django-rest-framework 和 swagger 中定义列表参数的正确方法

发布于 2025-01-11 08:34:46 字数 2249 浏览 0 评论 0原文

背景

我有以下视图,附带的 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)

我想实现以下目标:

  1. swagger UI 应该有一个参数 allowed_name_types ,它是 AllowedNameType< 的列表/code> 值
  2. 应根据序列化器定义对输入进行验证
  3. 应对 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(....)

这会导致以下界面: 在此处输入图像描述

不幸的是:

  1. swagger 组件需要一个 {"allowed_name_types 字典:...} 而不是列表,
  2. 列表元素的 allowed_name_types 验证不起作用(即我可以在列表中放置一个不是来自AllowedNameType的值)
  3. 奇怪的是,调用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:

  1. The swagger UI should have a parameter allowed_name_types which is a list of AllowedNameType values
  2. The input should be validated as per the serializer definition
  3. Type checking should be enforced on query_params to make sure the allowed_name_types is of type list[AllowedNameType] (ideally, allowed_name_types would actually be a named parameter in (eg list(..., 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: enter image description here

Unfortunately:

  1. The swagger component expects a dictionary of {"allowed_name_types:...} instead of a list
  2. 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)
  3. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文