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 5
Thanks, Nice Explanation
Posted 03 May 2009 at 5:33 pm ¶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 ¶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 :
Posted 04 Nov 2009 at 3:55 pm ¶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 ?
Thanks for this. One small correction:
Your password widget has rendervalue. It should be render_value.
Posted 29 Dec 2009 at 6:08 pm ¶Thanks for this tutorial. I find that django’s documentation will quite extensive seems to show you how you can customize everything but never shows you how to get started. I seriously spent several hours trying to figure out how to get the form to validate… finally found your site and had it work in like 2min. Arg…
Posted 18 Jun 2010 at 3:19 pm ¶Trackbacks & Pingbacks 1
[...] 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