Django
Forms
Validation
WHY SHOULD I USE DJANGO FORMS?
Never trust the client
- Easy to customize HTML output
- Validation is encapsulated
- Easy to report errors back to user
- Works well with models
WE WILL FOCUS ON VALIDATION THIS TIME

Let's assume there is no validation in client. That allows me to submit the form with values like these:

<form action="" method="GET">
Name: <input type="text" name="name" placeholder="name">
Email: <input type="text" name="email" placeholder="email">
Message: <textarea name="message" placeholder="Some space for your request"></textarea>
<input type="submit">
</form>
Our innocent server (it trusts clients) now wants to show back the data it got.
from django.http import HttpResponse
from django.template import RequestContext, loader
# Create your views here.
def my_view(request):
template = loader.get_template('my_faulty_template.html')
if request.GET.get('name'):
context = {
'name': request.GET.get('name'),
'email': request.GET.get('email'),
'message': request.GET.get('message'),
}
else:
context={}
return HttpResponse(template.render(context))
What a fool!
Our user should see something like this now:

<p>Name: {{ name }}</p>
<p>Email: {{ email }}</p>
<p>Message: {{ message }}</p>
Any errors on sight?
The email field, which is supposed to be an email, can be anything at the moment.
Never trust the client. Client side validation can be ignored easily, so we won't try to add that manually for now.
Let's focus on teaching our server how mean can clients be!
STEP 1: BUILD OUR DJANGO FORM
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(max_length=50)
email = forms.EmailField()
message = forms.CharField(max_length=200, widget=forms.Textarea)
STEP 2: CHANGE OUR VIEW
from django.http import HttpResponse
from django.template import RequestContext, loader
from .forms import ContactForm
def my_better_view(request):
template = loader.get_template('my_slightly_better_template.html')
context = {}
if request.method == 'GET':
form = ContactForm(request.GET)
if form.is_valid():
context = {
'name': form.cleaned_data['name'],
'email': form.cleaned_data['email'],
'message': form.cleaned_data['message'],
}
context['form'] = form
return HttpResponse(template.render(context))
STEP 3: UPDATE OUR TEMPLATE
<form action="" method="GET">
{{ form }}
<input type="submit">
</form>
<p>Name: {{ name }}</p>
<p>Email: {{ email }}</p>
<p>Message: {{ message }}</p>
YEAH...SO WHAT? WHAT CHANGED?
- We used an EmailField in server, which check that the entered value is indeed a valid email
- We rendered the form with Django. This is optional, but now our client is using an email input instead of a text input, adding some validation on client side
- If we decide to add more fields, we can just add them to our ContactForm class.
HOW CAN SERVER KNOW WHAT IS VALID AND WHAT IS NOT?
Let me introduce you your new right hand:
form.is_valid()
What if i want to show only the messages of love for Django Cali?
Time to get started with custom validations.
Let's change our ContactForm class
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(max_length=50)
email = forms.EmailField()
message = forms.CharField(max_length=200, widget=forms.Textarea)
def clean_message(self):
message = self.cleaned_data['message']
if 'I Love DjangoCali' not in message:
raise forms.ValidationError("What's wrong with you!!!")
return message
Ok, that was easy, wasn't it?
Let's try rejecting messages where the contact name has more than 2 words
def clean_name(self):
name = self.cleaned_data['name']
if len(name.split()) > 2:
raise forms.ValidationError("Your name is weird!!!")
return name
People with only one name is saying that they actually got 2 in their message! I don't want liars!
def clean(self):
cleaned_data = super(ContactForm, self).clean()
name = cleaned_data.get("name", '')
message = cleaned_data.get("message", '')
if len(name.split())==1 and 'i got 2 names' in message:
# Only do something if both fields are valid so far.
raise forms.ValidationError(
"I know you are lying!!!"
)
When should i use forms?
Forms are a must if you are accepting user input, of any kind.
Suppose we have a CSV file and we want to show it to our users or save it to the database. We need to make sure that every set of data is valid according to our rules. In this case you are not going to display the form, but you can use it to validate it.
my name is cristian,now i try breaking your csv,with dumb random text
three names yay,my@email.com,What should i do?
Two names,valid@email.com,I Love DjangoCali
Our test CSV
Our output
Contact_list:
- Name: Two names
- Email: valid@email.com
- Message: I Love DjangoCali
- ---------------------------------
How did you do that?
def my_csv_display(request):
template = loader.get_template('my_csv_data_display.html')
context = {}
my_valid_contacts = []
import csv
with open('my_app/csv_file.csv', 'rb') as csv_file:
reader = csv.reader(csv_file, delimiter=',')
for row in reader:
data={
'name': row[0],
'email': row[1],
'message': row[2],
}
form = ContactForm(data=data)
if form.is_valid():
my_valid_contacts.append(
[form.cleaned_data.get('name'),\
form.cleaned_data.get('email'),\
form.cleaned_data.get('message')]
)
context['contact_list'] = my_valid_contacts
return HttpResponse(template.render(context))
DRY
I just reused the same form we were using before, but for validating data from other source
I want to check the examples by myself, can i?
https://github.com/djangocali/forms_validation
PD: The functionality is there, but there is absolutely nothing helping with aesthetics, just the absolutely required bits to make it work.
Thanks for your attention
Django Forms Validation
By swapps
Django Forms Validation
Slides for presentation related to Django Forms Validation
- 641