代码之家  ›  专栏  ›  技术社区  ›  David Schumann Axnyff

Django视图:request.data是dict还是QueryDict?

  •  0
  • David Schumann Axnyff  · 技术社区  · 7 年前

    我在这个问题上遇到了一些麻烦,那个请求。数据有时是一个问题 dict (尤其是测试时)有时 QueryDict 实例(使用curl时)。

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

    或者像这样使用djangoèu webtest客户端:

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

    然后像这样把那个疑问抛给一个听写人

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

    在测试中一切正常,就像那里一样 request.data 口述 ,但在生产中,视图崩溃是因为 new_dict['some_float'] 实际上是一个包含一个元素的列表,而不是预期的浮点值。

    我考虑过这样解决这个问题:

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

    这感觉非常错误,因为测试只会测试第2行,和(一些?所有?)生产代码将运行第4行。

    查询信息 首先。以及如何使用django测试来模拟这种行为。为生产和测试系统设置不同的条件总是很麻烦,有时是不可避免的,但在这种情况下,我觉得它是可以修复的。或者这是一个与djangoèu webtest相关的特定问题?

    1 回复  |  直到 7 年前
        1
  •  9
  •   Saleh    6 年前

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

    在您的测试中,您发布JSON,然后它作为dict从 request.data . 但是您的curl调用发布了标准表单数据,可以作为QueryDict使用。这种行为是由 parsers

    你真的应该测试你正在做的事情;要么从curl发送JSON,要么让测试发布表单数据。

        2
  •  2
  •   user11430231    7 年前

    当您的请求内容类型为“application/x-www-form-urlencoded”时,request.Data变为QueryDict。

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

    以及

    QueryDict有get list方法。但它不能获取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
    

    和覆盖默认的\u解析器\u类。
    https://www.django-rest-framework.org/api-guide/settings/#default_parser_classes

    推荐文章