#25347 closed Cleanup/optimization (wontfix)
QueryDict can't return a list for a select multiple form element
Reported by: | Jonathan Drake | Owned by: | nobody |
---|---|---|---|
Component: | HTTP handling | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I'm not sure why this is the case but QueryDict can't return a list object for a multi select unless you explicitly call getlist. I'm not sure why this is the case since it should be able to translate the POST or GET data into the proper data structures.
"In an HttpRequest object, the GET and POST attributes are instances of django.http.QueryDict, a dictionary-like class customized to deal with multiple values for the same key. This is necessary because some HTML form elements, notably <select multiple>, pass multiple values for the same key."
This is from the documentation and it mentions that this custom class around the post data is needed to support it, yet doesn't explain why it's needed. No other language or framework I've worked with has this limitation where you need to explicitly know the form element's "type" before hand. This makes dynamically parsing the results impossible since you need to know the type before you can actually access it correctly.
Further more I don't see how returning the last element of a list is helpful in any real use cases. Clearly the class knows which data type it is if it can properly access the list element.
Change History (7)
comment:1 by , 9 years ago
comment:2 by , 9 years ago
I'm not sure how that's required. This isn't a bug but rather a limitation that I'm hoping can be fixed as a new feature.
If you iterate over request.POST
, I'm expecting that __getitem__
can handle giving me a list or a scalar depending on what was sent in the form data. Right now I have to know the actual key in order to extract the given key as a list so I don't end up with the last item in it.
The other alternative I have is to run getlist()
on every single key and then iterate over scalars as if they are lists which just adds unneeded overhead. I guess I could also roll out my own request data parser to replace QueryDict
, but it seems like this should be core functionality that QueryDict
can get right itself.
comment:3 by , 9 years ago
I recognize that this behavior is a bit awkward.
Now the question is: can we find a path to change this behavior without breaking lots of application code, as suddenly .get()
can return lists or scalars? Is it worth a plain backwards incompatibility?
comment:4 by , 9 years ago
Component: | Uncategorized → HTTP handling |
---|---|
Type: | Uncategorized → Cleanup/optimization |
Version: | 1.8 → master |
comment:5 by , 9 years ago
Proof of concept that allows QueryDict.get()
return to list. If it doesn't get any immediate negative reaction, I'll raise this idea on the mailing list.
comment:6 by , 9 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
I think there's a good reason QueryDict.get()
doesn't return a list if a key is specified multiple time (Compared to PHP's $_GET and $_POST) and it shouldn't be changed. Plus this is backward incompatible.
If I use self.request.GET.get('foo')
I'm expecting a str
to be returned and not a list
. User controlled input shouldn't be allowed to change the return type of .get()
and possibly introduce security issues.
e.g.
# This would work with ?pk=1 but cause a TypeError with ?pk=1&pk2 def view(request): pk = request.GET.get('pk') obj = Model.objects.get(pk=pk)
The same issue applies when using the Form api that relies on self.data.get
.
This is from the documentation and it mentions that this custom class around the post data is needed to support it, yet doesn't explain why it's needed. No other language or framework I've worked with has this limitation where you need to explicitly know the form element's "type" before hand. This makes dynamically parsing the results impossible since you need to know the type before you can actually access it correctly.
You should know before hand, independently of the form element "type" used, if you're expecting a parameter to be a scalar or a list of element. For example, if get()
was modified to return a list
if a key is specified more than once it would still return a scalar if you selected only one element in a select[type=multiple]
.
Closing as wontfix since this is highly backward incompatible and would introduce a subtle foot-gun for newcomers.
Could you include a failing test or a code snippet that demonstrates the expected vs. actual behavior?