AttributeError: 这个 QueryDict 实例对于测试用例是不可变的

Aar*_*shi 1 python django django-rest-framework django-tests

我正在尝试更改我的 request.data 字典以删除一些附加字段。它在视图中完全正常工作。但是当我运行相同的测试用例时,我收到此错误:

AttributeError: 这个 QueryDict 实例是不可变的

这是我的观点:

    def create(self, request, *args, **kwargs):

        context = {'view': self, 'request': request}

        addresses = request.data.pop("addresses", None)
        serializer = self.get_serializer(data=request.data, context=context)
        serializer.is_valid(raise_exception=True)
        response = super(WarehouseViewSet, self).create(request, *args, **kwargs)
        if addresses is None:
            pass
        else:
            serializer = self.get_serializer(data=request.data, context=context)
            serializer.is_valid(raise_exception=True)
            addresses = serializer.update_warehouse_address(request, addresses, response.data["id"])
            response.data["addresses"] = addresses
        return Response(data=response.data, status=status.HTTP_201_CREATED)
Run Code Online (Sandbox Code Playgroud)

这是我的相同视图的测试用例:

    def test_create_warehouse_authenticated(self):
        response = client.post(
            reverse('warehouse_list_create'),
            data={
                'name': self.test_warehouse['test_warehouse']['name'],
                'branch': self.test_warehouse['test_warehouse']['branch'],
            },
            **{'HTTP_AUTHORIZATION': 'Bearer {}'.format(
                self.test_users['test_user']['access_token']
            )},
        )

        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
Run Code Online (Sandbox Code Playgroud)

如何修复此错误?

And*_*ker 5

format='json'调用时尝试设置client.post,而不是依赖默认值。您没有提到您使用的是哪个测试客户端,但您应该使用APIClient

client = APIClient()
client.login(...)
client.post(..., format='json')
Run Code Online (Sandbox Code Playgroud)

较新的 Django 有一个不可变的 QueryDict,因此如果您从查询字符串或多部分表单主体获取数据,则始终会发生此错误。测试客户端multipart默认使用,这会导致此问题。

最后的手段:如果您需要发布多部分,并且还需要修改查询字典(非常罕见,请考虑发布图像 + 表单字段),您可以手动设置_mutableQueryDict 上的标志以允许更改它。这是

setattr(request.data, '_mutable', True)
Run Code Online (Sandbox Code Playgroud)