Django Rest框架验证:结合两个字段的“required”错误

时间:2018-04-20 09:11:12

标签: django django-rest-framework

我想将针对必填字段引发的错误合并到一个新属性中,例如从这个:

{'start_date': 'This field is required', 'end_date': 'This field is required'}

到此:

{'date': 'This field is required'}

起初我以为我可以在序列化程序的validate方法中进行验证,但似乎只在执行required验证后调用它。例如,以下内容不起作用:

class DatesRequiredSerializer(serializers.ModelSerializer):

    start_date = serializers.DateTimeField()
    end_date = serializers.DateTimeField()

    def validate(self, data):
        super().validate(data)
        # check if data is in either the request or instance
        start_date, end_date = None, None
        if 'start_date' in data:
            start_date = data['start_date']
        elif self.instance:
            start_date = self.instance.start_date

        if 'end_date' in data:
            end_date = data['end_date']
        elif self.instance:
            end_date = self.instance.end_date

        # this error isn't raised
        if not (start_date or end_date):
            raise serializers.ValidationError({"date": _('This field is required.')})

        return data

是否可以在不将序列化器字段设置为required=False的情况下组合验证?

P.S。如果有更简洁的方法来检查数据是否在请求/实例中,也很想知道!

1 个答案:

答案 0 :(得分:0)

覆盖to_internal_value中的serializers.Serializer,以创建自定义错误并将其添加到通常的必需异常中。

{
    "name": [
        "This field is required."
    ]
}

成为:

{
    "name": [
        "This field is required."
    ],
    "criteria_text": [
        "Either criteria_url or criteria_text is required"
    ],
    "criteria_url": [
        "Either criteria_url or criteria_text is required"
    ]
}

在我的情况下,用户需要填写criteria_textcriteria_url,如果他们失败,我想同时告诉他们,他们将得到通常的必需错误。

def to_internal_value(self, data):
    if data.get('criteria_text', None) is None and data.get('criteria_url', None) is None:
        errors = OrderedDict([('criteria_text', [ErrorDetail('Either criteria_url or criteria_text is required')]),
                              ('criteria_url', [ErrorDetail('Either criteria_url or criteria_text is required')])])
        try:
            super(MySerializer, self).to_internal_value(data)
            raise serializers.ValidationError(detail=errors)
        except serializers.ValidationError as e:
            e.detail = OrderedDict(chain(e.detail.items(), errors.items()))
            raise e
    else:
        return super(MySerializer, self).to_internal_value(data)