Reputation: 333
I have a ModelViewSet defined as below:
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
and the corresponding ModelSerializer is:
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
Assume request.data
will contain a json payload: {"purchase_order": 1, "approver": 1}
, based on those two attributes, I can find the corresponding purchase_order_approver, then, I want to update is_approved
to True
via the method approve
defined in PurchaseOrderApproverSerializer
.
the model is defined as below:
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)
Because the serializer can only receive data that have been defined in the serializer, so, I have to find the object via a filter in the viewset first, then, initiate a serializer to call the function defined in the serializer to update the object. But I am pretty sure DRF provides a better (or simpler) way to do it.
I am looking for something such as customized viewset method or override the update method in serializer to achieve this purpose.
Upvotes: 0
Views: 470
Reputation: 1517
Maybe, inside your serializer method approve()
, you can use the Serializer's context, then you have access to the request. Based on that you should get the request.data
.
Inside your Serializer method:
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)
Upvotes: 1