[Fixed]-Django Views: When is request.data a dict vs a QueryDict?

5👍

When your request content_type is “application/x-www-form-urlencoded”, request.Data become QueryDict.

see FormParser class.
https://github.com/encode/django-rest-framework/blob/master/rest_framework/parsers.py

And

QueryDict has get lists method. but it can’t fetch dict value.
convert name str to array.

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

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

And define custom form 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

And overwite DEFAULT_PARSER_CLASSES.
https://www.django-rest-framework.org/api-guide/settings/#default_parser_classes

14👍

Your test isn’t a reflection of your actual curl call.

In your test, you post JSON, which is then available as a dict from request.data. But your curl call posts standard form data, which is available as a QueryDict. This behaviour is managed by the parsers attribute of your view or the DEFAULT_PARSER_CLASSES settings – and further note that this is functionality specifically provided by django-rest-framework, not Django itself.

Really you should test the same thing as you are doing; either send JSON from curl or get your test to post form-data.

Leave a comment