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.