The suggested pattern for processing a form in a view seems overly complex and non-DRY to me:
def contact(request):
if request.method == 'POST': # If the form has been submitted...
form = ContactForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
return HttpResponseRedirect('/thanks/') # Redirect after POST
else:
form = ContactForm() # An unbound form
return render_to_response('contact.html', {
'form': form,
})
That's a lot of conditionals, it repeats the ContactForm() construction, and the whole block is repeated everywhere a view needs to process a form. Isn't there a better way of doing it?
You can avoid the repetition, of course. Mostly, you need to pass in as arguments the class of form and template name to use, a callable to process the cleaned data when a valid form is submitted, and a destination for the redirect after such processing; plus, you need a little extra code to call the form class just once, to produce either a bound or unbound form, and deal with it properly. I.e.:
def process_any_form(request,
form_class, template_file_name,
process_data_callable, redirect_destination):
form = form_class(request.POST if request.method == 'POST' else None)
if form.is_bound and form.is_valid():
process_data_callable(form.cleaned_data)
return HttpResponseRedirect(redirect_destination)
return render_to_response(template_file_name, {'form': form})
You are right it could be better, here is a better alternative (but keep reading):
def contact(request):
form = ContactForm(request.POST or None) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
return HttpResponseRedirect('/thanks/') # Redirect after POST
return render_to_response('contact.html', {
'form': form,
})
This snippet comes from a talk called Advanced Django Form Usage from DjangoCon11.
Note that this will process an empty form as valid (even before submission) if all the fields are optional and you don't use CSRF protection. So to eliminate that risk, you better use this one:
def contact(request):
form = ContactForm(request.POST or None) # A form bound to the POST data
if request.method == 'POST' and form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
return HttpResponseRedirect('/thanks/') # Redirect after POST
return render_to_response('contact.html', {
'form': form,
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With