允许在 Django Rest Framework 序列化器字段名称中使用连字符

jam*_*esc 5 python django django-rest-framework

鉴于我正在编写代码的 OpenAPI 规范要求在请求正文中使用连字符大小写(又名 kebab-case)变量名称,在使用 Django Rest Framework 时应该如何处理?

例如,POST /thing创建事物的请求具有以下主体:

{
    "owner-type": "platform"
}
Run Code Online (Sandbox Code Playgroud)

但是在Python,owner-type不是有效的变量名(“语法错误:无法分配给经营者”),这样反而Thingowner_type在模型中定义:

{
    "owner-type": "platform"
}
Run Code Online (Sandbox Code Playgroud)

但现在ThingSerializer有问题,因为再次owner-type是一个非法名称。这是不允许的:

class Thing(models.Model):
    owner_type = models.CharField(max_length=8)
Run Code Online (Sandbox Code Playgroud)

我试图ModelSerializer通过尝试调整由 生成的字段名称来覆盖名称的生成方式get_fields(),但它失败了。这是我的序列化程序:

    owner-type = serializers.CharField(...)
Run Code Online (Sandbox Code Playgroud)

和错误:

../venv/lib/python3.6/site-packages/rest_framework/fields.py:453: in get_attribute
    return get_attribute(instance, self.source_attrs)
../venv/lib/python3.6/site-packages/rest_framework/fields.py:101: in get_attribute
    instance = getattr(instance, attr)
E   AttributeError: 'Thing' object has no attribute 'owner-type'
Run Code Online (Sandbox Code Playgroud)

所以我的问题 - 如何配置 DRF 模型序列化器以允许包含下划线的模型字段被序列化/反序列化,以便 API 客户端看到连字符而不是下划线?这将是上面示例的通用解决方案,其中Thing.owner_type应该通过"owner-type"在 JSON 正文中传递字段来读取/写入。

我在 Python 3.6 上使用最新的 Django 和 DRF。

编辑 1:澄清理想情况下,这将是将下划线转换为连字符的通用解决方案。

moj*_*eto 8

您可以使用连字符定义字段名称,fields并通过定义source属性将其映射到正确的 django 模型字段extra_kwargs- 请参阅https://www.django-rest-framework.org/api-guide/serializers/#additional-keyword-arguments

要回答您的问题,您定义ThingSerializer如下:

class ThingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Thing
        fields = [
            'owner-type',
        ]
        extra_kwargs = {
            'owner-type': {'source': 'owner_type'},
        }
Run Code Online (Sandbox Code Playgroud)

  • 只有“ModelSerializer”能够做到这一点。`Serializer` [始终使用类上定义的属性名称](https://github.com/encode/django-rest-framework/blob/7f3a3557a050147dd2420aa41d1bf7ddd7f9818e/rest_framework/serializers.py#L285-L287)。 (2认同)

JPG*_*JPG -1

这在使用 models 时没有用,但可以回答字段中连字符的使用,请按如下所示更改序列化器


class ThingSerializer(serializers.Serializer):
   def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields.update({"owner-type": serializers.CharField(write_only=True)})
 
Run Code Online (Sandbox Code Playgroud)