Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

request.<method> is empty with Django 1.5 #6

Closed
ppo opened this issue Apr 1, 2013 · 7 comments
Closed

request.<method> is empty with Django 1.5 #6

ppo opened this issue Apr 1, 2013 · 7 comments

Comments

@ppo
Copy link

ppo commented Apr 1, 2013

In Django 1.5, HttpRequest._load_post_and_files():
If content-type doesn't start with "'multipart/form-data'" or "application/x-www-form-urlencoded", an empty QueryDict is set, it no more uses request.body.

Django 1.4.5: https://github.com/django/django/blob/1.4.5/django/http/__init__.py#L380
Django 1.5.1: https://github.com/django/django/blob/1.5.1/django/http/request.py#L231

@nick2k5
Copy link
Contributor

nick2k5 commented Apr 12, 2013

Hm, yeah this is a problem. I've played around here and I can't find any great solutions that don't feel really slimy. Any thoughts @croach

@croach
Copy link
Owner

croach commented Apr 26, 2013

@nick2k5 the explanation below is a little long winded and goes into an addition to the framework that would help alleviate some of the problems, so you can skip to the end to get the tl;dr version of the answer if you want.

Basically, it looks like Django is moving more and more into the modern era of web development. In the past nearly everything sent to the server came via a form submission, so it was a fairly safe assumption that all data sent in an HTTP POST was of the format sent by an HTML form. However, that's no longer the case. It's now very plausible that data is sent to the server via an HTTP POST using any number of media types (e.g., JSON).

With this new change, the maintainers of Django are basically saying that they are no longer making an assumption of what type of data is being sent, but instead they are relying solely on the Content-type header to tell them what the media type is. So, if the Content-type is set to application/www-form-urlencoded, then it will parse it as HTML form data and put the resultant data into the POST QueryDict. If, however, the Content-type is not specified, or is something else other than regular HTML form data, it will place the raw data into the raw_post_data attribute and leave the parsing of that data up to the developer.

So, given all of this, it looks like both Django and the framework are acting correctly. If you send data via an HTML form, the data will end up in the POST QueryDict since the default Content-type the browser sets is application/www-form-urlencoded. The problem occurs only when data is POSTed via some other mechanism (e.g., JavaScript or a non-web client). In this case, the solution is just to set the Content-type to application/www-form-urlencoded before sending the data, which is what we should be doing anyway, but have gotten away with not doing it up until now due to Django's lax handling of POST data in the past.

There is one thing that would be nice to add to the framework and that would be handlers for media types other than the ones that Django handles (i.e., file uploads and form submissions). So, for example, if you wanted to accept JSON data, the client could set the Content-type to application/json, send it, and the framework would call the JSON parser to convert the data into a python dict. Then that could be added to the POST QueryDict instead of leaving it up to the developer to parse the data from the raw_post_data attribute. This would still mean that the developer would have to correctly set the Content-type before sending the data, and so probably would not help in this case since I'm sure the reason the data isn't showing up in POST now is due to the lack of a Content-type rather than an unsupported one.

tl;dr This is the correct behavior. In the past Django has been too lax on how it handles POST data and has just assumed that all POST data comes from a form submission. This is no longer a valid assumption in this modern era of single page web apps and RESTful APIs, so Django has tightened its handling of POST data. To make sure that your data shows up in the POST QueryDict, simply make sure that the Content-type header is set to application/www-form-urlencoded before POSTing the data to the server.

@nick2k5
Copy link
Contributor

nick2k5 commented May 2, 2013

@croach Thanks for this. Looks like a reasonable requirement (to require the header be set appropriately) -- I will add this to the docs.

@nik-hil
Copy link

nik-hil commented Feb 22, 2014

@croach thanks for this. saved my day. Also learnt few bytes.

@jjmontesl
Copy link

Should this issue be closed?

@ppo
Copy link
Author

ppo commented Nov 13, 2015

I guess it can now.

@ppo ppo closed this as completed Nov 13, 2015
@rasheedh
Copy link

Thanks a lot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants