Django Rest Framework:根据从ModelViewSet接收的任意数据更新ModelSerializer中的对象 - 寻找更好的解决方案

时间:2018-04-03 13:50:08

标签: python django-rest-framework

我有一个ModelViewSet定义如下:

class PurchaseOrderApproverViewSet(viewsets.ModelViewSet):
    queryset = PurchaseOrderApprover.objects.all()

    @list_route(methods=['POST'])
    def approve_purchase_order(self, request):
        purchase_order = request.data['purchase_order']
        approver = request.data['approver']
        purchase_order_approver = 
        PurchaseOrderApprover.objects.filter(approver=approver, 
        purchase_order=purchase_order).first()
        if purchase_order_approver:
            serializer = PurchaseOrderApproverSerializer()
            serializer.approve(purchase_order_approver)
            content = {'success'}
            return Response(content, status=status.HTTP_200_OK)
        else:
            raise Http404

和相应的ModelSerializer是:

class PurchaseOrderApproverSerializer(serializers.ModelSerializer):

    class Meta:
        model = PurchaseOrderApprover
        exclude = ('purchase_order', )

    @transaction.atomic()
    def approve(self, instance):
        instance.is_approved = True
        purchase_order = instance.purchase_order
        all_approved = True

        for purchase_order_approver in PurchaseOrderApprover.objects.filter(purchase_order=purchase_order):
            if not purchase_order_approver.is_approved:
                all_approved = False

        if all_approved:
            purchase_order.status = APPROVED
            purchase_order.save()
        instance.save()
        return instance

假设request.data将包含json有效负载:{"purchase_order": 1, "approver": 1},基于这两个属性,我可以找到相应的purchase_order_approver,然后,我想将is_approved更新为{{1} }通过True中定义的方法approve

模型定义如下:

PurchaseOrderApproverSerializer

因为序列化程序只能接收已在序列化程序中定义的数据,所以,我必须先通过视图集中的过滤器找到对象,然后启动序列化程序来调用序列化程序中定义的函数来更新宾语。但我很确定DRF提供了更好(或更简单)的方法。

我正在寻找自定义视图集方法或覆盖序列化器中的更新方法以实现此目的。

1 个答案:

答案 0 :(得分:1)

也许,在序列化方法approve()中,您可以使用Serializer的上下文,然后您就可以访问该请求了。基于此,您应该获得request.data

在Serializer方法中:

request = self.context.get('request')

# In cases of your data came as a GET params 
print(request.query_params)
# Normal post/patch/put method request data
print(request.data)