I modify response.data in Django REST Framework view.py. Why am I getting an AttributeError during testing but not with actual API use?
My Django REST Framework API is working just as expected. In view.py, I modify OrderViewSet, def partial_update, to add another key/value pair to the response.data dict before it is saved to the db. It works without errors when I call the API with Postman.
However, when I run tests for the same functionality it fails and returns:
request.data["submission_date"] = datetime.now()
AttributeError: This QueryDict instance is immutable
Why would I get this error during testing if it is not occurring during actual API use?
View.py
class OrderViewSet(viewsets.ModelViewSet):
""" Includes custom PATCH functionality """
queryset = Order.objects.all().order_by('-order_date')
serializer_class = OrderSerializer
authentication_classes = (authentication.TokenAuthentication,)
permission_classes = [permissions.IsAuthenticated]
def partial_update(self, request, *args, **kwargs):
""" Update status and timestamp fields accordingly """
status = request.data['status']
if status == 'submitted':
request.data["submission_date"] = datetime.now()
if status == 'packaged':
request.data["packaged_date"] = datetime.now()
if status in ['sold', 'canceled', 'abandoned']:
request.data["finished_date"] = datetime.now()
return super().partial_update(request, *args, **kwargs)
Test.py
def test_patch_order_status_from_cart_to_submitted(self):
""" test patching order status from cart to submitted """
order = sample_order(user=self.user)
payload = {
"status": "submitted"
}
res = self.client.patch(order_detail_url(order.id), payload)
self.assertEqual(res.status_code, status.HTTP_200_OK)
patched_order = Order.objects.get(id=order.id)
self.assertEqual(patched_order.status, 'submitted')
def test_submitted_timestamp(self):
""" test that patching order status to submitted also leaves timestamp """
order = sample_order(user=self.user)
payload = {
"status": "submitted"
}
self.client.patch(order_detail_url(order.id), payload)
patched_order = Order.objects.get(id=order.id)
self.assertNotEqual(patched_order.submission_date, None)
You mean modifying request.data? I also got this error before.
Then I read Django documentation QueryDict, I think the "request.data":
is dictionary-like, not dictionary.
data type is immutable.
copy that before modifying, like:
req_data = request.data.copy() req_data['submission_date'] = datetime.now()
And the reason of error not occurring during actual API use, maybe just the status not in these conditions.
On the other hand, in this case I usually set a modified_at or created_at DateTimeField in models.py, so that will record the submission_date automatically whenever the data is modified or created. I feel that is convenient.
created_at = models.DateTimeField(auto_now_add=True, help_text="submission_date")
modified_at = models.DateTimeField(auto_now=True, help_text="re-submission_date")