As the title asks, why did the Django guys decide to implement the request.POST object with a querydict (which, of course, in turn, makes the whole thing immutable?)
I know you can mutify it by making a copy of the post data
post = request.POST.copy()
but why do this? Surely it would be simpler just to allow the thing to be mutable anyway? Or is it being used for some other reason too which might cause issue?
It’s a bit of a mystery, isn’t it? Several superficially plausible theories turn out to be wrong on investigation:
So that the
POSTobject doesn’t have to implement mutation methods? No: thePOSTobject belongs to thedjango.http.QueryDictclass, which implements a full set of mutation methods including__setitem__,__delitem__,popandclear. It implements immutability by checking a flag when you call one of the mutation methods. And when you call thecopymethod you get anotherQueryDictinstance with the mutable flag turned on.For performance improvement? No: the
QueryDictclass gains no performance benefit when the mutable flag is turned off.So that the
POSTobject can be used as a dictionary key? No:QueryDictobjects are not hashable.So that the
POSTdata can be built lazily (without committing to read the whole response), as claimed here? I see no evidence of this in the code: as far as I can tell, the whole of the response is always read, either directly, or viaMultiPartParserformultipartresponses.To protect you against programming errors? I’ve seen this claimed, but I’ve never seen a good explanation of what these errors are, and how immutability protects you against them.
In any case,
POSTis not always immutable: when the response ismultipart, thenPOSTis mutable. This seems to put the kibosh on most theories you might think of. (Unless this behaviour is an oversight.)In summary, I can see no clear rationale in Django for the
POSTobject to be immutable for non-multipartrequests.