在安静的CreateAPIView
中,我突变了request.data
字典。
有时,我会收到一个未被测试发现的错误:
This QueryDict instance is immutable
例如这个:
class CreateView(CreateAPIView):
serializer_class = ...
queryset = ...
def post(self, request, *args, **kwargs):
request.data['user'] = request.user.pk
return self.create(request, *args, **kwargs)
request.data
在我的测试中似乎是正常的dict
。为什么有时有时QueryDict
?应该如何处理?一般而言,request.data不应被突变吗?当您需要自己填充某些字段时,应该如何使用ModelSerializer
类?
答案 0 :(得分:5)
为什么这种偶然行为?
当我们查看SC of Request(如@Kenny Ackerman提到的)时,如果您传递的是 表单媒体,它将返回 QueryDict
对象在视图类中输入 ('application/x-www-form-urlencoded'
或'multipart/form-data'
)数据。
该检查在 {{ 1}} 类。
如果要将Request
数据传递到视图,则 application/json
将是 request.data
对象。
如何重现行为?
可以通过向视图中发送不同的dict
数据来进行复制。 (在POSTMAN工具中,使用ContentType
和form-data
来获取行为)
如何在序列化程序中获取 当前登录用户 ?
方法1 通过覆盖 raw JSON
将额外的参数传递给 .save()
(如@Linovia所述)方法
perform_create()
方法2 使用is_form_media_type()
类,如下所示
class CreateView(CreateAPIView):
serializer_class = ...
queryset = ...
def post(self, request, *args, **kwargs):
request.data['user'] = request.user.pk
return self.create(request, *args, **kwargs)
def perform_create(self, serializer):
serializer.save(user=self.request.user)
答案 1 :(得分:1)
基于source code解析器,当流为空(request.data调用_load_data_and_files
方法和_load_data_and_files
调用_parse
方法)时,对数据返回一个querydict。>
,我认为您可以使用HiddenField填充字段,也可以覆盖create
或update
方法。例如
class TestSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model = Test
fields = ('id', 'text', 'user')
def create(self, validated_data):
validated_data['populate_field'] = 'value'
return super().create(validated_data)
答案 2 :(得分:1)
当您必须修改从请求接收到的QueryDict对象时,它是一个不可变的对象,如果要添加属性,请改用以下代码:
myNewRequest = request.GET.copy()
myNewRequest.data['some_attr'] = float(something)
答案 3 :(得分:0)
请注意,这实际上取决于rest_framework的DEFAULT_PARSER_CLASSES
中指定的所选解析器和请求的内容类型:
JSONParser的实现如下:
return json.load(decoded_stream, parse_constant=parse_constant)
FormParser如下:
return QueryDict(stream.read(), encoding=encoding)