Я изменяю response.data в Django REST Framework view.py. Почему я получаю ошибку AttributeError во время тестирования, но не при реальном использовании API?

Мой Django REST Framework API работает так, как ожидалось. В view.py я модифицирую OrderViewSet, def partial_update, чтобы добавить еще одну пару ключ/значение в дикту response.data перед сохранением в БД. Это работает без ошибок, когда я вызываю API с помощью Postman.

Однако, когда я запускаю тесты для той же функциональности, они не работают и возвращают:

request.data["submission_date"] = datetime.now()
AttributeError: This QueryDict instance is immutable

Почему я могу получить эту ошибку во время тестирования, если она не возникает во время фактического использования API?

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)

Вы имеете в виду изменение request.data? Я также получал эту ошибку раньше.

Потом я прочитал Django документацию QueryDict, я думаю, что "request.data":

  • является словареподобным, а не словарем.

  • тип данных неизменяемый.

  • копируйте это перед модификацией, например:

     req_data = request.data.copy()
     req_data['submission_date'] = datetime.now()
    

А причина того, что ошибка не возникает при реальном использовании API, может быть просто статус не в этих условиях.

С другой стороны, в этом случае я обычно устанавливаю modified_at или created_at DateTimeField в models.py, так что это автоматически записывает дату отправки_даты всякий раз, когда данные изменяются или создаются. Мне кажется, что это удобно.

created_at = models.DateTimeField(auto_now_add=True, help_text="submission_date")
modified_at = models.DateTimeField(auto_now=True, help_text="re-submission_date")
Вернуться на верх