Using Django's New Form Engine
The Django web framework's new form engine (not yet released, but available from the project's Subversion repository: see the Django installation page) eliminates much of the pain in creating and updating data submitted by users.
As an example I've written a Django app using a design pattern that is likely to be familiar to those coming from a PHP background.
This simple example allows the creation, updating, and deletion of contacts.
Project Setup
Start a project named 'myproject' and, within the project, an application named 'contacts'.
Edit your project's settings.py file and make the following changes:
The View
Edit the contacts/views.py file to contain the following code:
The Template
Last, we have to define our Django template.
Create a file at html/contacts.html that contains the following code:
Note the use of request.path in the template: this is similar to the use of $_SERVER['PHP_SELF'] in PHP.
The End Result
Now that we've set up the project and defined a model, view, and template we synchronize the database and run the test server with the commands below:
With any luck, the application should now be accessable via http://localhost:8000/contacts.
$ django-admin.py startproject myproject $ cd myproject $ python manage.py startapp contacts $ mkdir html
Edit your project's settings.py file and make the following changes:
- Configure your database (sqlite3 is convenient)
- Add 'myproject.contacts' to your INSTALLED_APPS list
- Add 'html' to your TEMPLATE_DIRS list
from django.db import models # Create your models here. class Contact(models.Model): name = models.CharField(maxlength=200) phone = models.CharField(maxlength=200)
The View
Edit the contacts/views.py file to contain the following code:
from myproject.contacts.models import Contact
from django import newforms as forms
from django.shortcuts import render_to_response
def main(request):
# initialize variables to sent to template
message = ''
submit_action = 'Add'
edit_id = ''
# generate default form
ContactForm = forms.form_for_model(Contact)
f = ContactForm()
# handle edit and delete events
if request.method == 'GET':
if request.has_key('edit_id'):
# replace default form with form based on row to edit
contact = Contact.objects.get(pk=request.GET['edit_id'])
ContactForm = forms.form_for_instance(contact)
f = ContactForm()
submit_action = 'Update'
edit_id = request.GET['edit_id']
message = 'Editing contact ID ' + request.GET['edit_id']
if request.has_key('delete_id'):
Contact.objects.get(pk=request.GET['delete_id']).delete()
message = 'Contact deleted.'
# handle add and update events
if request.method == 'POST':
if request.POST['submit_action'] == 'Add':
# attempt to do add
add_f = ContactForm(request.POST)
if add_f.is_valid():
add_f.save()
message = 'Contact added.'
else:
# validation failed: show submitted values in form
f = add_f
if request.POST['submit_action'] == 'Update':
# attempt to do update
contact = Contact.objects.get(pk=request.POST['edit_id'])
ContactForm = forms.form_for_instance(contact)
update_f = ContactForm(request.POST.copy())
if update_f.is_valid():
update_f.save()
message = 'Contact updated.'
else:
# validation failed: prepare form for new update attempt
submit_action = 'Update'
edit_id = request.POST['edit_id']
f = update_f
# get existing contacts
contact_list = Contact.objects.all()
# return rendered HTML page
return render_to_response(
'contacts.html',
{ 'request': request,
'message': message,
'contact_list': contact_list,
'form': f.as_table(),
'submit_action': submit_action,
'edit_id': edit_id
}
)The Template
Last, we have to define our Django template.
Create a file at html/contacts.html that contains the following code:
<html>
<head>
<title>Contacts</title>
</head>
<body>
{% if message %}
<b>{{ message }}</ b>
<p />
{% endif %}
{% if contact_list %}
<table>
{% for contact in contact_list %}
<tr bgcolor='{% cycle FFFFFF,EEEEEE as rowcolor %}'>
<td>{{ contact.name }}</td>
<td><a href='{{ request.path }}?edit_id={{ contact.id }}'>Edit</a></td>
<td><a href='{{ request.path }}?delete_id={{ contact.id }}'>Delete</a></td>
</tr>
{% endfor %}
</table>
<p />
{% endif %}
<form action='{{ request.path }}' method='POST'>
<input type='hidden' name='edit_id' value='{{ edit_id }}'>
<table>
{{ form }}
<tr>
<td colspan=2 align=right>
<input type=submit name='submit_action' value='{{ submit_action }}'>
</td>
</tr>
</table>
</form>
{% ifnotequal submit_action 'Add' %}
<p />
<a href='{{ request.path }}'>Add New Contact</a>
{% endifnotequal %}
</html>The End Result
Now that we've set up the project and defined a model, view, and template we synchronize the database and run the test server with the commands below:
$ python manage.py syncdb $ python manage.py runserver
