Log in

No account? Create an account
entries friends calendar profile Elf Sternberg's Pendorwright Projects Previous Previous Next Next
Django Gotchas: Django’s request.GET dictionary and ‘in’ - Elf M. Sternberg
Django Gotchas: Django’s request.GET dictionary and ‘in’

I wish I’d known this a long time ago.  Django’s request object includes a dictionary of key/value pairs passed into the request via POST or GET methods.  That dictionary, however, works in a counter-intuitive fashion.  If a URL reads http://foo.com?a=boo, then the expected content of request.GET['a'] would be 'boo', right?  And most of us who’ve used other URL parsers in the past know that http://foo.com?a=boo&a=hoo know that the expected content of request.GET['a'] would be ['boo', 'hoo'].

Except it isn’t.  It’s just 'hoo'.  Digging into the source code, I learn that in Django’s MultiValueDict, __getitem__(self, key) has been redefined to return the last item of the list.  I have no idea why.  Maybe they wanted to ensure that a scalar was always returned.  The way to get the whole list (necessary when doing an ‘in’ request) is to call request.GET.getlist('a').

Lesson learned, an hour wasted.

This entry was automatically cross-posted from Elf's technical journal, ElfSternberg.com

Tags: , ,

15 comments or Leave a comment
orcaarrow From: orcaarrow Date: October 24th, 2010 07:27 pm (UTC) (Link)
I bow and marvel at your programing-foo!
elfs From: elfs Date: October 25th, 2010 05:19 am (UTC) (Link)
UTSL (Use The Source, Luke!)
dossy From: dossy Date: October 24th, 2010 09:46 pm (UTC) (Link)
Ah, yet another instance of Perl's "wantarray" envy. It's the one "feature" of Perl that I actually wish other languages had - override by return value. Otherwise, you end up with goofy things like forcing the return of a scalar and introducing a new method to get the list value, like Elf discovered.
wolfwings From: wolfwings Date: October 25th, 2010 10:39 am (UTC) (Link)
Agreed. And many times I do only want a scalar, and don't want to have to consider someone trying to break my code by force-feeding multiple instances of the same operator in. Handling such a multiple-instance case seems like the exception, not the standard M.O. to me? Or is there some common situation with newer website designs I haven't run across yet there such is no longer the case and adding both X=Y and X=Z occurs often now?
elfs From: elfs Date: October 25th, 2010 01:20 pm (UTC) (Link)
I'm not familiar with any. It does seem that there was a specific use case a developer was aiming for, and somehow that use case ended up as being canon in the code. Very annoying.
wolfwings From: wolfwings Date: October 25th, 2010 02:52 pm (UTC) (Link)
Well... I meant more, I'm trying to see a usage case where getting a list back is an obviously-correct use case versus only returning the single scalar?

And seperately, why returning the last instead of the first value is more sensible?
elfs From: elfs Date: October 25th, 2010 05:05 pm (UTC) (Link)
I think that's why Dossy brought up wantarray. Because according to the W3C recommendation, the scalar is the special case, the list the common case.
wolfwings From: wolfwings Date: October 25th, 2010 06:19 pm (UTC) (Link)
Yeah... and I'm trying to figure out their reasoning for the list being the common case. It's likely some approach to development I'm missing, or an assumption that was made back then that's turned out to not be true in today's untrusted-input reality of web design. I just can't think of any interface I've ever seen made or made myself that would want to allow multiple instances of the same variable to be passed into a web form.
bolindbergh From: bolindbergh Date: October 25th, 2010 11:14 pm (UTC) (Link)
It's what you get from a <select name="foo" multiple> form element.
wolfwings From: wolfwings Date: October 26th, 2010 01:23 am (UTC) (Link)
Ah... just hadn't thought of that for some reason, thank you.
elfs From: elfs Date: October 25th, 2010 11:59 pm (UTC) (Link)
What bolindbergh wrote, along with a fairly standard "collection of check boxes." Different values, same key, as only the ones checked get sent back to the server.
wolfwings From: wolfwings Date: October 26th, 2010 01:22 am (UTC) (Link)
Derp... just hadn't thought of that. Even ran into and handled that once in the past once now that I think of it, just oozed out of my ears in the time since.
(Deleted comment)
bolindbergh From: bolindbergh Date: October 27th, 2010 05:31 pm (UTC) (Link)
At least I know of no generally accepted standard whatsoever that states that standard URL query parameters may be treated as multidimensional variables.

RFC 1866: Hypertext Markup Language - 2.0 from November 1995. The example form submission contains exactly what we're talking about here. This feature remains in all newer versions, including the latest HTML 5 draft.

elfs From: elfs Date: October 27th, 2010 05:59 pm (UTC) (Link)
Specifically, section of RFC 1866 covers this detail:
An <INPUT> element with `TYPE=CHECKBOX' represents a boolean choice.
A set of such elements with the same name represents an n-of-many choice field.
Section 8.2.4 outlines form processing and is explicit in describing multiple name/value pairs being treated in a key/value-array fashion. Although this operation is described mostly in the context of n-of-many choices, the contents of the values are free-form within the constraints of form processing, and no requirements are placed on the server to distinguish between checkboxes and other form elements using the same facility.

Frank appears to be confusing a common (but not universal) operation of the "equals" symbol as found in many (but not all) programming languages (see: Scheme, Pascal, Erlang, among others) with section 8.2.4's specialized (but linguistically acceptible) compromise with respect to the tokenization of CGI arguments.

Edited at 2010-10-27 06:02 pm (UTC)
(Deleted comment)
elfs From: elfs Date: October 29th, 2010 03:28 pm (UTC) (Link)
It's also important to know that order of the name/value pairs is "exactly as they appear in the DOM at the time of submission." This is really useful if you're dynamically adding to your form. I had to do that for my movie company, where we were adding Actor/Role pairs. Since it's hard to know how many actors there are in a movie, I dynamically added a new (blank) pair using Javascript to the bottom of the fieldset with every entry. Browsers that supply javascript honor the strict order, and it was easy to find the actor/role pair by index.
15 comments or Leave a comment