【问题标题】:DRF: accessing a SerializerMethodField during serializer validationDRF:在序列化程序验证期间访问 SerializerMethodField
【发布时间】:2015-01-18 14:10:24
【问题描述】:

我正在使用 Django Rest Framework 3.0,并且我有一个模型:

class Vote(models.Model):
    name = ...
    token = models.CharField(max_length=50)

其中token 是我从request IP 信息生成的唯一标识符,以防止同一用户投票两次

我有一个序列化器:

class VoteSerializer(serializers.ModelSerializer):
    name = ...
    token = serializers.SerializerMethodField()

    class Meta:
        model = Vote
        fields = ("id", "name", "token")

    def validate(self, data):
        if Rating.objects.filter(token=data['token'], name=data['name']).exists():
            raise serializers.ValidationError("You have already voted for this")
        return data

    def get_token(self, request):
        s = ''.join((self.context['request'].META['REMOTE_ADDR'], self.context['request'].META.get('HTTP_USER_AGENT', '')))
        return md5(s).hexdigest()

还有一个CreateView

但我得到了一个

KeyError: 'token' 

当我尝试发布并创建一个新的Vote 时。为什么验证时数据中不包含token字段?

The docs mention

它可用于将任何类型的数据添加到对象的序列化表示中。

所以我原以为它也会在validate 期间可用?

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    调查,似乎在验证发生后调用了SerializerMethodField 字段(没有深入研究代码,我不知道这是为什么 - 这似乎违反直觉)。

    我已将相关代码移到视图中(老实说,这实际上在概念上更有意义)。

    要使其正常工作,我需要执行以下操作:

    class VoteCreateView(generics.CreateAPIView):
        serializer_class = VoteSerializer
    
        def get_serializer(self, *args, **kwargs):
            # kwarg.data is a request MergedDict which is immutable so we have
            # to copy the data to a dict first before inserting our token
            d = {}
            for k, v in kwargs['data'].iteritems():
                d[k] = v
            d['token'] = self.get_token()
            kwargs['data'] = d
            return super(RatingCreateView, self).get_serializer(*args, **kwargs)
    
        def get_token(self):
            s = ''.join((self.request.META['REMOTE_ADDR'], self.request.META.get('HTTP_USER_AGENT', '')))
            return md5(s).hexdigest()
    

    我真的希望这不是执行此操作的正确方法,因为对于看似非常直截了当的情况而言,这似乎完全令人费解。希望其他人可以为此发布更好的方法。

    【讨论】:

    • 已经很久了,你知道为什么吗?因为6年多以后还是一样的……
    猜你喜欢
    • 1970-01-01
    • 2020-08-14
    • 2017-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多