You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建支持CharField或字符列表的Django Serializer字段并适配DRF Spectacular

实现支持字符串或字符串列表的Serializer字段并适配DRF Spectacular

要实现同时支持单个字符串或字符串列表的Serializer字段,并且让DRF Spectacular正确生成包含两种类型的API文档,可以按以下步骤操作:

1. 自定义Serializer字段

继承DRF的Field类,重写类型校验和序列化逻辑,同时兼容两种输入类型:

from rest_framework import serializers

class CharOrListCharField(serializers.Field):
    def __init__(self, **kwargs):
        # 初始化嵌套的CharField和ListField,传递所有参数(如max_length)
        self.char_validator = serializers.CharField(**kwargs)
        self.list_validator = serializers.ListField(child=serializers.CharField(**kwargs), **kwargs)
        super().__init__(**kwargs)

    def to_internal_value(self, data):
        # 校验输入:优先尝试列表类型,失败则尝试字符串类型
        if isinstance(data, list):
            return self.list_validator.to_internal_value(data)
        try:
            return self.char_validator.to_internal_value(data)
        except serializers.ValidationError:
            raise serializers.ValidationError("该字段必须是字符串或字符串列表")

    def to_representation(self, value):
        # 序列化输出:保留原类型结构
        if isinstance(value, list):
            return self.list_validator.to_representation(value)
        return self.char_validator.to_representation(value)

2. 适配DRF Spectacular文档生成

通过extend_schema_field装饰器,让字段生成包含两种类型的OpenAPI Schema(使用oneOf关键字):

from drf_spectacular.utils import extend_schema_field

@extend_schema_field({
    "oneOf": [
        {"type": "string"},
        {"type": "array", "items": {"type": "string"}}
    ]
})
class CharOrListCharField(serializers.Field):
    # 上述自定义字段的代码

如果需要传递CharField的额外约束(如max_length)到Schema中,可以完善Schema定义:

@extend_schema_field(lambda field: {
    "oneOf": [
        {
            "type": "string",
            "maxLength": field.char_validator.max_length if hasattr(field.char_validator, 'max_length') else None
        },
        {
            "type": "array",
            "items": {
                "type": "string",
                "maxLength": field.char_validator.max_length if hasattr(field.char_validator, 'max_length') else None
            }
        }
    ]
})
class CharOrListCharField(serializers.Field):
    # 上述自定义字段的代码

3. 在Serializer中使用字段

直接在Serializer类中声明该字段即可:

class MySerializer(serializers.Serializer):
    my_field = CharOrListCharField(max_length=100)
    # 其他字段...

这样配置后,该字段既可以接收单个字符串或字符串列表作为输入,DRF Spectacular生成的API文档也会明确标注该字段支持两种类型。

内容的提问来源于stack exchange,提问作者Slav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 17:42:39