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

时间:2019-04-05 11:19:45

标签: python django django-rest-framework

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

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

{
    "owner-type": "platform"
}

但是在Python中,owner-type不是有效的变量名(“ SyntaxError:无法分配给运算符”),因此Thing在模型定义中具有owner_type:< / p>

class Thing(models.Model):
    owner_type = models.CharField(max_length=8)

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

    owner-type = serializers.CharField(...)

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

class ThingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Thing
        fields = [
            'owner_type',
        ]

    def get_fields(self):
        fields = super().get_fields()
        out_fields = OrderedDict()
        for field_name, field in fields.items():
            out_fields[field_name.replace('_', '-')] = field
        return out_fields

错误:

../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'

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

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

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

2 个答案:

答案 0 :(得分:0)

将序列化器更改为belwo,

class ThingSerializer(serializers.ModelSerializer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields.update({"owner-type": serializers.CharField(write_only=True)})


    class Meta:
        model = Thing
        fields = '__all__'
        read_only_fields = ('owner_type',)

    def create(self, validated_data):
        validated_data['owner_type'] = validated_data.pop('owner-type')
        return super().create(validated_data)

答案 1 :(得分:0)

您可以在fields中用连字符定义字段名称,并通过在source中定义extra_kwargs属性将其映射到正确的Django模型字段-请参见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'},
        }