Django视图:什么时候request.data是dict还是QueryDict



我遇到了一些问题,request.data有时是一个dict(尤其是在测试时(,有时是QueryDict实例(使用curl时(。

这尤其是一个问题,因为当使用curl这样调用视图时,显然有很大的区别:

curl -X POST --data "some_float=1.23456789012123123" "http://localhost:8000/myview"

或者像这样使用django_webtest客户端:

class APIViewTest(WebTest):
def test_testsomething(self):
self.app.post(url=url, params=json.dumps({some_float=1.26356756467}))

然后将QueryDict转换为类似的dict

new_dict = dict(**request.data)
my_float = float(new_dict['some_float'])

在测试中一切都很好,因为request.datadict,但在生产中视图崩溃,因为new_dict['some_float']实际上是一个包含一个元素的列表,而不是预期的浮点值。

我已经考虑过这样解决问题:

if type(request.data) is dict:
new_dict = dict(**request.data)
else:
new_dict = dict(**request.data.dict())

这感觉非常错误,因为测试只测试第2行,而(一些?全部?(生产代码将运行第4行。

因此,当我想知道QueryDict为什么会这样做时,我更想知道response.data为什么以及何时是QueryDict。以及如何使用django测试来模拟这种行为。生产和测试系统的条件不同总是很麻烦,有时也是不可避免的,但在这种情况下,我觉得这是可以解决的。或者这是一个与django_webtest相关的特定问题?

您的测试并不是实际curl调用的反映。

在测试中,您发布JSON,然后可以从request.data中获得该JSON作为dict。但是您的curl调用发布标准表单数据,该数据可以作为QueryDict使用。此行为由视图的parsers属性或DEFAULT_PARSER_CLASSES设置管理,请进一步注意,这是django-rest框架专门提供的功能,而不是django本身。

实际上,你应该在做同样的事情时进行测试;从curl发送JSON,或者让测试发布表单数据。

当您的请求content_type为"application/x-www-form-urlencoded"时,请求。数据变为QueryDict。

请参阅FormParser类
https://github.com/encode/django-rest-framework/blob/master/rest_framework/parsers.py

QueryDict具有get-lists方法。但它无法获取dict值
将名称str转换为数组。

<input name="items[name]" value="Example">
<input name="items[count]" value="5">  

https://pypi.org/project/html-json-forms/

并定义自定义表单paser。

class CustomFormParser(FormParser):
"""
Parser for form data.
"""
media_type = 'application/x-www-form-urlencoded'
def parse(self, stream, media_type=None, parser_context=None):
"""
Parses the incoming bytestream as a URL encoded form,
and returns the resulting QueryDict.
"""
parser_context = parser_context or {}
encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET)
data = QueryDict(stream.read(), encoding=encoding)
return parse_json_form(data.dict()) # return dict

并覆盖DEFAULT_PARSER_CLASSES
https://www.django-rest-framework.org/api-guide/settings/#default_parser_classes

最新更新