串行器验证功能不称为DRF

时间:2018-03-21 07:22:49

标签: python django api django-rest-framework

semanage fcontext -a httpd_sys_rw_content_t "/var/www/tmp(/.*)?"

在发布时不调用验证函数,另外如何向ChildSerializer提供自定义错误,

5 个答案:

答案 0 :(得分:1)

您的ParentSerializer验证方法存在一些问题。假设您的title模型中有ParentSerializer字段。对于字段级验证,您将获得字段而不是整个数据。那就是validate_title函数应该title(数据的标题字段)作为参数而不是data。因此,您无需检查data.get('title')是否存在titleReference

class ParentSerializer(serializers.ModelSerializer):
    """
    Serializer for task
    """
    def validate_title(self, title):
        if not title:
            raise serializers.ValidationError('Please set title')
        return title

答案 1 :(得分:0)

正如我在评论中提到的那样,您应该调用is_valid()方法来调用field validation methodsvalidate_title()views.py等。 所以你应该在from rest_framework.views import APIView class MyView(APIView): def get(self, request): data = some_data_or_instance # assuming this is the object/data to be serialized serializer = ParentSerializer(data=data) serializer.is_valid(True) # This will call fielsd validation methods in the serializer return Response(data={"message": "custom message"})

中做到这一点
frmCustomerSearch

答案 2 :(得分:0)

我遇到了一个类似的问题,即未调用我的自定义验证字段。我正在编写它来绕过不正确的DRF验证(更多详细信息如下所示,但对于回答不是必需的。)

查看DRF源代码时,我发现了我的问题:DRF始终在使用自定义代码进行验证之前使用其代码来验证您的字段。

''' rest-framework/serializers.py '''

for field in fields:
    validate_method = getattr(self, 'validate_' + field.field_name, None)
    primitive_value = field.get_value(data)
    try:
        # DRF validation always runs first!
        # If DRF validator throws, then custom validation is not called
        validated_value = field.run_validation(primitive_value)
        if validate_method is not None:
            # this is your custom validation
            validated_value = validate_method(validated_value)
    except ValidationError as exc:
        errors[field.field_name] = exc.detail
    except DjangoValidationError as exc:
        errors[field.field_name] = get_error_detail(exc)

答案:自定义验证器不能用于绕过DRF的验证器,因为它们将始终首先运行,并会在您可以说是有效的之前引发异常。

(对于感兴趣的人,我遇到的验证错误是这样的:用于ModelA的ModelSerializer与ModelB具有OneToOne关系。ModelB的pk具有UUID。DRF在验证时会引发错误'53abb068-0286-411e-8729-0174635c5d81' is not a valid UUID.,这是不正确的,而且确实令人生气。)

答案 3 :(得分:0)

除了@ sean.hudson的回答外,我还试图弄清楚如何覆盖子序列化程序验证。

通过覆盖ParentSerialzer的to_internal_value,可以“跳过”或更准确地忽略子级序列化程序验证错误:

class ParentSerializer(serializers.ModelSerializer):
    children = ChildSerializer(many=True)

    def to_internal_value(self, *args, **kwargs):
        try:
            # runs the child serializers
            return super().to_internal_value(*args, **kwargs)
        except ValidationError as e:
            # fails, and then overrides the child errors with the parent error
            return self.validate(self.initial_data)

    def validate(self, attrs):
        errors = {}
        errors['custom_override_error'] = 'this ignores and overrides the children serializer errors'
        if len(errors):
            raise ValidationError(errors)
        return attrs
    class Meta:
        model = Parent

答案 4 :(得分:0)

我的问题是我有自己的自定义to_internal_value方法。删除它可以解决问题。

class EventSerializer(serializers.Serializer):
    end_date = serializers.DateTimeField(format=DATE_FORMAT, required=True)
    start_date = serializers.DateTimeField(format=DATE_FORMAT, required=True)
    description = serializers.CharField(required=True)


    def validate_start_date(self, start_date):
        return start_date

    def validate_end_date(self, end_date):
        return end_date

    # def to_internal_value(self, data):
    #     if data.get('start_date', False):
    #         data['start_date'] = datetime.strptime(data['start_date'], DATE_FORMAT)
    #     if data.get('end_date', False):
    #         data['end_date'] = datetime.strptime(data['end_date'], DATE_FORMAT)
    #     return data