Django Rest框架、模型序列化程序和自定义字段验证

Django Rest框架、模型序列化程序和自定义字段验证,django,django-rest-framework,Django,Django Rest Framework,使用最新版本的Django和DRF 我有一个相当复杂的需求,我找不到解决方案。我会尽量简化它 假设我有一个有两个字段的模型。字段a和字段b 我有一个模型序列化程序。我发布了一个带有字段的请求。这些字段使用模型进行验证,然后根据我的两个序列化程序函数validate_field_a和validate_field_b进行验证。一切都很好 现在我希望我的POST请求包含第三个字段,该字段不是该模型的成员。让我们称之为field_c。我有一个自定义的def createself,validated_da

使用最新版本的Django和DRF

我有一个相当复杂的需求,我找不到解决方案。我会尽量简化它

假设我有一个有两个字段的模型。字段a和字段b

我有一个模型序列化程序。我发布了一个带有字段的请求。这些字段使用模型进行验证,然后根据我的两个序列化程序函数validate_field_a和validate_field_b进行验证。一切都很好

现在我希望我的POST请求包含第三个字段,该字段不是该模型的成员。让我们称之为field_c。我有一个自定义的def createself,validated_data:在我的序列化程序中,它将所有内容保存到数据库中

关于field_c,我想:

自定义验证它。就像我处理其他两个字段一样。 要求整个请求必须成功,否则,发出“字段是必需的”错误,就像我忘记发布一个必需的模型字段一样。 有机会获取字段_c并将其保存到数据库中完全不同的不相关模型行中。 我似乎无法回避这个问题。如果我将字段c添加到字段元,它会抛出一个异常,合理地说字段c不在我的模型中。如果我不在字段中包含它,那么我真正想放在那里的validate_field_c甚至不会被调用


我能做什么

不要为此使用ModelSerializer-使用序列化程序重新创建与您的模型相同的字段并像您希望的那样包含字段

我知道您希望您的模型在验证过程中做一些工作,但DRF的设计将这些责任隔离开来。你可以阅读更多关于它的内容。基本上,序列化程序应该是完成所有验证工作的那个

当然,这意味着您必须在序列化程序中显式定义验证方法


在自定义创建方法中,您可以创建模型实例或根据需要在其中执行任何操作。

您可以在序列化程序中添加自定义字段作为只写字段,并重写创建方法,以便处理自定义字段的值

大概是这样的:

class MySerializer(serializers.ModelSerializer):
    field_c = serializers.CharField(write_only=True)

    class Meta:
        model = MyModel
        fields = ('field_a', 'field_b', 'field_c')

    def validate_field_c(self, value):
        if value is 'test':
            raise ValidationError('Invalid')
        return value

    def create(self, validated_data, **kwargs):
        field_c = validated_data.pop('field_c')

        return MyModel.objects.create(**validated_data)

这将在模型和序列化程序中创建重复的验证规则。最好将验证保留在模型中,继续从ModelSerializer继承,并在绝对必要时通过覆盖run_validation来自定义验证,例如调整self.fields['field_name'].验证器。