DRF:验证后但在创建之前删除模型序列化程序上的字段(在CreateAPIView上)

时间:2015-12-02 18:48:21

标签: django django-rest-framework

我在发布到CreateAPIView的网站上有一个联系表单,用于创建模型的新实例(最终通过电子邮件发送给管理员)。在我的序列化程序中,我有一个蜜罐字段来帮助拒绝垃圾邮件。

模特:

class Message(models.Model):
    name = ...
    message = ...

和序列化器:

class MessageSerializer(serializers.ModelSerializer):

    # Honeypot field
    url = serializers.CharField(allow_blank=True, required=False)

    class Meta:
        model = Message
        fields = '__all__'

    def validate_url(self, value):
        if value and len(value) > 0:
            raise serializers.ValidationError('Spam')
        return value

并查看:

class MessageView(generics.CreateAPIView):
    ''' Create a new contact form message. '''
    serializer_class = MessageSerializer

我的问题在于,当我发布到此视图时,我收到错误:

  

TypeError:调用TypeError时获得Message.objects.create()。这可能是因为序列化程序类上的可写字段不是Message.objects.create()的有效参数。您可能需要将该字段设置为只读,或覆盖MessageSerializer.create()方法以正确处理此字段。

很明显,seriazlier正在尝试将url字段保存到CreateApiView.perform_create()

中的模型

我尝试将read_only添加到序列化程序字段,但这意味着完全跳过url_validate方法。

如何在验证发生之前将字段保留在序列化程序中,在serializer.save()中调用perform_create()之前将其删除?

2 个答案:

答案 0 :(得分:5)

你可以这样做覆盖create方法,如:

class MessageSerializer(serializers.ModelSerializer):

    # Honeypot field
    url = serializers.CharField(allow_blank=True, required=False)

    class Meta:
        model = Message
        fields = '__all__'

    def validate_url(self, value):
        if value and len(value) > 0:
            raise serializers.ValidationError('Spam')
        return value

    def create(self, validated_data):
        data = validated_data.pop('url')
        return Message.objects.create(**data)

答案 1 :(得分:0)

好的,我没有正确读取错误。正如它清楚地说:

  

重写MessageSerializer.create()方法以正确处理此问题。

我正在考虑覆盖那些没有意义的CreateAPIView.create()方法。

这有效:

class MessageSerializer(serializers.ModelSerializer):

    # Honeypot field
    url = serializers.CharField(allow_blank=True, required=False)

    class Meta:
        model = Message
        fields = '__all__'

    def validate_url(self, value):

        if value and len(value) > 0:
            raise serializers.ValidationError('Error')
        return value

    def create(self, validated_data):
        if "url" in validated_data:
            del validated_data["url"]
        return Message.objects.create(**validated_data)