Django Rest Framework在序列化之前更新数据

And*_*osa 8 django django-rest-framework

我希望任何用户都可以使用我的RESTful API创建自己的产品。为此,我创建了一个继承ListCreateAPIView的视图。问题在于用户只能创建自己拥有的产品,因此在创建Product模型的实例时,我希望字段Owner对应于经过身份验证的用户。

这是我的产品型号

class Product(models.Model):
    owner = models.ForeignKey(User)
    name = models.CharField(max_length=30)
Run Code Online (Sandbox Code Playgroud)

显然我的序列化器是:

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Product
Run Code Online (Sandbox Code Playgroud)

和我的看法:

class ProductView(generics.ListCreateAPIView):
    queryset = models.Product.objects.all()
    serializer_class = serializers.ProductSerializer
    permission_classes = (IsAuthenticatedOrReadOnly,)

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        #serializer.initial_data['owners'] = models.Person.objects.get(user__email=request.user).user_id
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)

        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
Run Code Online (Sandbox Code Playgroud)

如您所见,我尝试修改“ initial_data”,但这是一个QueryDict,它是不可变的。另一个选择是将其转换为Python字典,然后添加“所有者”值,但是这样做时,我将每个值都作为列表获取(即{'name':['MyName']}),所以这将是一个非常解决问题的方法很丑,我认为应该是一个更直接的解决方案。

Rah*_*pta 8

您可以覆盖perform_create()当前用户并将其作为传递owner。然后,在Product创建实例时,owner将使用当前用户值保存字段。

class ProductView(generics.ListCreateAPIView):
    queryset = models.Product.objects.all()
    serializer_class = serializers.ProductSerializer
    permission_classes = (IsAuthenticatedOrReadOnly,)

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user) # pass the current user as the 'owner'
Run Code Online (Sandbox Code Playgroud)

另外,您应该在序列化程序中将字段定义ownerread_only。然后,在反序列化期间将不需要该字段。但是,此字段将包含在序列化的输出中。

 class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Product
        extra_kwargs = {'owner': {'read_only':True}} # set 'owner' as read-only field 
Run Code Online (Sandbox Code Playgroud)

  • 这样做的问题是,在执行is_valid()之后调用perform_create函数,并且没有所有者字段的情况下序列化程序无效,因此create函数将在执行perform_create之前引发异常。 (2认同)