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

时间:2016-07-03 05:54:50

标签: django django-rest-framework

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

这是我的产品型号

class Product(models.Model):
    owner = models.ForeignKey(User)
    name = models.CharField(max_length=30)

显然我的序列化器是:

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Product

和我的观点:

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)

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

3 个答案:

答案 0 :(得分:5)

您可以覆盖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'

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

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

答案 1 :(得分:0)

下面的简单解决方案。 owner将在请求GET / POST / PUT等中不可见,但会自动分配给当前经过身份验证的用户。

from rest_framework.serializers import (CurrentUserDefault, HiddenField,
                                        ModelSerializer)

class ProductSerializer(ModelSerializer):
    owner = HiddenField(default=CurrentUserDefault())

    class Meta:
        model = models.Product

答案 2 :(得分:0)

您可以在视图中传递初始数据,然后在序列化程序中重写默认值

views.py

class ItemListCreateView(ListCreateAPIView):

    def get_serializer_context(self):
        return {"delivery_request": self.kwargs['req_pk']}

serializers.py

class ItemCreateSerializer(ModelSerializer):
    delivery_request = CharField(default='')

    def validate_delivery_request(self, value):
        try:
            value = DeliveryRequest.objects.get(
                id=self.context["delivery_request"])
        except DeliveryRequest.DoesNotExist:
            raise ValidationError(
                self.Meta.error_messages['delivery_request_not_found'])
        return value

PS。当您想要填充来自url的Null数据时,它非常有用,例如