team glu

an open source application lifecycle management solution

one step forward and two steps back or maybe it's one back and one to the right

I’ve been wrestling with how I can bring a choice list through from my model to a form in my template. After hours of research I decided it was time to discuss the topic with (beg for help from) a good mate who is knowledgeable in all things django.

My current technique for building forms in Team Glu to date is to write a 'read’, 'edit’ and 'save’ view which passes objects to the relevant template. Within a template I would hand code a form in HTML, similar to this;

<h1>Editing {{ project.name }} Details</h1>
<form method="post" action="/projects/{{ project.slug }}/save/">
<div class="form-row">
	<label class="required" for="title">Name</label>
	<input type="text" readonly="readonly" name="name" value="{{ project.name }}" />
</div>
<div class="form-row">
	<label class="required" for="title">Summary</label>
	<input type="text" name="summary" value="{{ project.summary }}" />
</div>
<div class="form-row">
	<label class="required" for="description">Description</label>
	<textarea name="description" rows="10" cols="55">{{ project.description }}</textarea>
	<p class="help-text">(wiki markup allowed)</p>
</div>
<div class="form-row">
	<label for="created_by">Created by</label>
	<input type="text" readonly="readonly" name="created_by" value="{{ project.created_by }}" />
</div>
<input type="submit" value="save"/>
</form>

It was Brads suggestion that I should look at django forms to handle the construction of my forms as django forms include some lovely helpers to build 'select’ lists of model choice fields.

I decided to give django forms a trial (as I found my current method quiet flexible), but very quickly realised the benefits of django forms. through the use of django forms I was able to combine my 'edit’ and 'save’ views (possibly I could have done this anyway) and reduce the hand crafted code in my template to look like this;

<form method="post" action="/projects/{{ project.slug }}/save/">
	<div class="form-row">
		<label class="required" for="title">Name</label>
		<p>{{ project.name }}</p>
	</div>
	{% for field in form %}
	<div class="form-row">
		{{ field.errors }}
		{{ field.label_tag }} {{ field }}
		{% if field.help_text %}
			<p class="help-text">{{ field.help_text }}</p>
		{% endif %}
	</div>
	{% endfor %}
	<div class="form-row">
		<label class="required" for="created_by">Created by</label>
		<p>{{ project.created_by }}</p>
	</div>
	<input type="submit" value="save"/>
</form>

Defining the form is as simple as defining a model, plus I now get free validation.

from django import forms
class ProjectDetail(forms.Form):
    summary = forms.CharField(max_length=200)
    description = forms.CharField(widget=forms.Textarea, help_text='wiki markup allowed')

What does this mean for Team Glu, well… I really don’t think a blanket conversion of forms is needed. However, I am going to convert any existing form that I feel really will benefit from being a django form as the highest priority task. Another delay, but for a good cause.

Django forms, you had me at 'hello’.

Added on March 15, 2011