Often one initializes a form with:
def someview(request): form = MyForm(request.POST or None) # …
This is often used to construct a form for both the GET and the POST request since it seems to make things shorter.
Although it is common, a POST request does not per se has content. The
or operator evaluates the truthiness of the
request.POST operand, and if it is
False, it will take the right operand (so
None). This means that even if it is a POST request, it will take
None, and thus as result the form is not bounded.
If the form is not bounded, then
form.is_valid() will return
False, even if an empty
request.POST was a valid request.
We can branch based on the request method, and use
request.POST in case of a POST request:
def someview(request): if request.method == 'POST': form = MyForm(request.POST, request.FILES) # … else: form = MyForm() # …