﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
27989	Passing an empty QueryDict to a form stores it as a plain dictionary	Stefan Wehrmeyer	Abhishek Gautam	"Passing an empty {{{request.POST}}} or {{{request.FILES}}} into a form, evaluates the arguments to {{{False}}} [https://github.com/django/django/blob/ea36e7454c267aab933e92481288e1eab636cd62/django/forms/forms.py#L79-L80 in these lines] and stores a normal Python dictionary instead.

{{{
self.data = data or {}
self.files = files or {}
}}}

This breaks the assumption that what you pass into the form will be kept allowing access to special methods like {{{QueryDict.getlist}}}.

The following code accepts zero or more uploaded files, but breaks when no files are uploaded because the passed {{{QueryDict}}} gets discarded and a {{{dict}}} has no method {{{getlist}}}.

{{{
class UploadForm(forms.Form):
    documents = forms.FileField(
        required=False,
        widget=forms.FileInput(attrs={
          'multiple': True
        })
    )

    def save(self):
        for doc in self.files.getlist('documents'):
            handle_doc(doc)


form = UploadForm(request.POST, request.FILES)
form.save()

# When request.FILES is empty
# AttributeError: 'dict' object has no attribute 'getlist'

}}}

Instead of 
{{{
self.data = data or {}
self.files = files or {}
}}}
it should be something like
{{{
self.data = QueryDict() if data is None else data
self.files = QueryDict() if files is None else files
}}}
which would keep whatever was passed except {{{None}}} and fall back to an empty {{{QueryDict}}} instance which is the type of the usual parameter.

The only backwards incompatible change here would be that {{{self.data}}} and {{{self.files}}} are no longer mutable as they would be when set to empty {{{dict}}}s, but afaik the attributes are not changed anyway."	Bug	closed	Forms	dev	Normal	fixed			Accepted	1	0	0	0	1	0
