DjangoRestFramework-序列化程序验证会引发KeyError,即使它是由perform_create()方法提供的
这是我的视图集:DjangoRestFramework-序列化程序验证会引发KeyError,即使它是由perform_create()方法提供的,django,django-rest-framework,Django,Django Rest Framework,这是我的视图集: class PostViewSet(viewsets.ModelViewSet): queryset = Post.objects.all() serializer_class = PostSerializer permission_classes = (IsAuthenticated, IsLikeOrOwnerDeleteOrReadOnly,) def perform_create(self, serializer): #
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = (IsAuthenticated, IsLikeOrOwnerDeleteOrReadOnly,)
def perform_create(self, serializer):
# Passing location to the serializer.
serializer.save(owner=self.request.user, location=self.request.user.userextended.location)
这是我的序列化程序:
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ('id', 'owner', 'post', 'page', 'location')
read_only_fields = ('id', 'owner', 'location')
def create(self, validated_data):
post = Post(
owner = validated_data['owner'],
post = validated_data['post'],
location = validated_data['location'],
)
if validated_data.get('page', None):
post.page = validated_data['page']
post.save()
return post
def validate(self, data):
if not data.get('page', None):
return data
# The KeyError being raised points to the line below.
if data['location'] == data['page']:
return data
raise serializers.ValidationError('Error.')
问题是,即使我从我的perform\u create()
方法将locaiton
传递给序列化程序,我在尝试创建帖子时也会遇到一个错误。错误是:
if data['location'] == data['page']:
KeyError: 'location'
我假设DRF在执行perform\u create()
方法之前进行序列化程序验证检查?如果是,我如何完成我需要的?(即,当从我的视图将位置
传递给序列化程序并且页面
来自我的序列化程序时,我如何检查数据['location']==data['page']
)。serializer.save(owner=request.user)
任何其他关键字参数都将包含在
调用.create()或.update()时验证了\u数据参数
因此,您只能在create()
或update()
方法中访问额外的关键字参数,而不能在validate()
那么,如何将额外的数据传递给序列化程序呢?使用上下文序列化程序
在视图中重写get\u serializer\u context
方法
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = (IsAuthenticated, IsLikeOrOwnerDeleteOrReadOnly,)
get_serializer_context(self):
return {'location':self.request.user.userextended.location}
然后在验证序列化程序方法中
def validate(self, data):
if not data.get('page', None):
return data
location = self.context.get('location')
if location == data['page']:
return data
raise serializers.ValidationError('Error.')
啊好的。根据您的回答,我意识到我也可以在验证函数中执行此操作:
location=self.context.get('request',None.).user.userextended.location
。这与您提到的方法(即从视图的get\u serializer\u context()
方法返回location
)有什么不同(在性能和最佳实践方面)?@user2719875取决于,在我看来,您的可读性更强,只需要使用self.context.get('location')
来获取用户位置,想象一下你需要做一个更复杂的操作,以你的方式,你需要一次又一次地重复那个“计算”。重写get_serializer_上下文的目的是完全归档您正试图执行的操作。也要确保模型的外键(如“User”)具有属性null=True
,这样您就可以在perform\u create
上插入它。否则,即使在调用perform\u create
之前,也会引发错误。