Python Django Rest框架:基于从ModelViewSet接收的任意数据更新ModelSerializer中的对象-寻找更好的解决方案

Python Django Rest框架:基于从ModelViewSet接收的任意数据更新ModelSerializer中的对象-寻找更好的解决方案,python,django-rest-framework,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.da

我有一个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
class PurchaseOrderApprover(BaseModel):
    purchase_order = models.ForeignKey(PurchaseOrder, related_name='purchase_order_approvers', on_delete=models.CASCADE)
    approver = models.ForeignKey(User, on_delete=models.PROTECT)
    is_approved = models.BooleanField(default=False)
相应的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负载:
{“采购订单”:1,“审批人”:1}
,根据这两个属性,我可以找到相应的采购订单审批人,然后,我想通过
PurchaseOrderApproverSerializer
中定义的
approve
方法将
是否已批准
更新为
True

模型定义如下:

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
class PurchaseOrderApprover(BaseModel):
    purchase_order = models.ForeignKey(PurchaseOrder, related_name='purchase_order_approvers', on_delete=models.CASCADE)
    approver = models.ForeignKey(User, on_delete=models.PROTECT)
    is_approved = models.BooleanField(default=False)
因为序列化程序只能接收序列化程序中定义的数据,所以我必须首先通过视图集中的过滤器找到对象,然后启动序列化程序调用序列化程序中定义的函数来更新对象。但我非常确信DRF提供了一种更好(或更简单)的方法


我正在寻找自定义视图集方法或重写序列化程序中的更新方法来实现此目的。

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

在序列化程序方法中:

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)

太棒了,谢谢@luan fonseca,它可以工作,但是需要在我的ModelView serializer=PurchaseOrderApproverSerializer(context={'request':request})中添加一个额外的输入,因为我手动创建了这个序列化程序,所以,我还必须手动将上下文从viewset传递到序列化程序。您认为通过提供两个自定义函数(一个在viewset中,一个在serializer中)来实现这一点是最好的方法吗?有没有其他方法可以通过在viewset中创建方法或重写serializer中的方法来实现同样的效果?嘿,我认为您应该在viewset上使用
serializer\u class
参数,请参见drf示例:但这可能会破坏某些东西,因为我认为实现的serializeré只是为了创建/更新。