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:

{% if error %}
 
{{ error }}
 
{% endif %}
<form action="." method="post">
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>

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:

<h1>Welcome, {{ username }}</h1>

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.

Comments 4

  1. Puneet wrote:

    Thanks, Nice Explanation

    Posted 03 May 2009 at 5:33 pm
  2. Brent wrote:

    Found a little bug. If your view is named “login”, this collides with the “login” function that you call inside the view itself, resulting in this error when you try to log in:

    TypeError at /login/

    login() takes exactly 1 argument (2 given)

    To fix this, your view should be named anything else. Like “mylogin”.

    Posted 12 May 2009 at 3:59 am
  3. Dimitris wrote:

    I googled and googled a lot, found so many info but in the end only your piece run smoothly. Plus it is understandable the way it is writen.
    One question though… Instead of redirecting to the logged_in.html, can we have a direct redirection in a create.html ( which has a view also named create(responce) ), and it is supposed to accept data that will eventually be writen to database ?
    So imagine…1.Login, 2.Accepted Login, 3.new form, for data-entry 4.Save 5.redirect wherever…

    What I tried is instead this :
    return render_to_response(’courses/logged_in.html’, {’username’: username,})
    to
    return create(request)
    and right before create, set perhaps request method to ‘GET’. But it fails.
    Any suggestion ?

    Posted 04 Nov 2009 at 3:55 pm
  4. Mark wrote:

    Thanks for this. One small correction:

    Your password widget has rendervalue. It should be render_value.

    Posted 29 Dec 2009 at 6:08 pm

Trackbacks & Pingbacks 1

  1. From Alan deLevie - Django login script code snippet on 27 Dec 2008 at 12:33 am

    [...] off what I learned making my previous tutorial A simple introduction to Django forms, I made a somewhat more elegant login script which includes the ability to log out (what a novel [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *