DRF:在序列化程序验证期间访问 SerializerMethodField
DRF: accessing a SerializerMethodField during serializer validation
我正在使用 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'
当我尝试 post 并创建一个新的 Vote
时。为什么验证时 token
字段不包含在数据中?
It can be used to add any sort of data to the serialized representation of your object.
所以我还以为 validate
期间也可以使用它?
调查,似乎 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()
我真的希望这不是正确的方法,因为对于看似非常简单的情况来说,这似乎完全令人费解。希望其他人可以 post 更好的方法来解决这个问题。
我正在使用 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'
当我尝试 post 并创建一个新的 Vote
时。为什么验证时 token
字段不包含在数据中?
It can be used to add any sort of data to the serialized representation of your object.
所以我还以为 validate
期间也可以使用它?
调查,似乎 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()
我真的希望这不是正确的方法,因为对于看似非常简单的情况来说,这似乎完全令人费解。希望其他人可以 post 更好的方法来解决这个问题。