A simple introduction to Django forms

As a Django noob neophyte, it took me some time to figure out how to create and handle forms. After a few headaches and sifting through a decent amount of documentation, I have learned the basic structure of creating a form using Django. The following will be a simple tutorial showing you how to create a login form using Django. The tutorial assumes that you are already familiar with Django. A Django form will typically consist of a class in models.py, a function in views.py, and a template. So in models.py we will create a form and give it two fields, 'username' and 'password'.
class LoginForm(forms.Form):
	username = forms.CharField(max_length=100)
	password = forms.CharField(widget=forms.PasswordInput(rendervalue=False),max_length=100)
Notice the 'widget' argument. Because this is a password field, we want the text of the password to be hidden. By telling Django that this is a password field, any rendering of this form will automatically have the requisite html to hide the text. This is one of the many conveniences of using Django. Since we are creating a login form, the views.py file must contain a function which authenticates the username and password. Here is the views.py file:
from django.contrib.auth import authenticate, login
from django.shortcuts import render_to_response
def login(request):
	def errorHandle(error):
		form = LoginForm()
		return render_to_response('login.html', {
				'error' : error,
				'form' : form,
		})
	if request.method == 'POST': # If the form has been submitted...
		form = LoginForm(request.POST) # A form bound to the POST data
		if form.is_valid(): # All validation rules pass
			username = request.POST['username']
			password = request.POST['password']
			user = authenticate(username=username, password=password)
			if user is not None:
				if user.is_active:
					# Redirect to a success page.
					login(request, user)
					return render_to_response('courses/logged_in.html', {
						'username': username,
					})
				else:
					# Return a 'disabled account' error message
					error = u'account disabled'
					return errorHandle(error)
			else:
				 # Return an 'invalid login' error message.
				error = u'invalid login'
				return errorHandle(error)
		else:
			error = u'form is invalid'
			return errorHandle(error)
	else:
		form = LoginForm() # An unbound form
		return render_to_response('login.html', {
			'form': form,
		})
This function first checks if any POST data exists. If the form is valid (ie, all fields are filled in), POST data is grabbed and checked against the database of existing users. The series of if/else statements simply checks for various errors which are then assigned to the "error" variable. At the top of this function, I have defined an error-handling function which outputs the login template with the form and error dictionaries included as context variables. If the username and password are correct, a "success" template is loaded with the username as a context dictionary. Here is the login.html template:
For those not familiar with Django's template language: The first line simply checks if an error variable exists. If it does, it displays the proper error within "p" tags. The "form.as_p" specifies how you want Django to render your form. as_p means the form will be rendered as a series of p tags. If you'd like, you can write form.as_table, which will, as you may guess, render the form as a table. More brownie points for Django. Here is the logged_in.html template:

Welcome,

This line simply displays the username variable which was sent to it as an argument in the render_to_response function. Obviously, this is the part of the site that only logged-in users can access. This is where my tutorial ends and your own creativity begins. You can view the end result of this tutorial at djangosnippets.org.
Alan 14 December 2008