#17301: Defining fieldsets in a form class
-----------------------------+------------------------------------
Reporter: msiedlarek | Owner: nobody
Type: New feature | Status: new
Component: Forms | Version: SVN
Severity: Normal | Keywords: form, forms, fieldsets
Triage Stage: Unreviewed | Has patch: 1
Easy pickings: 0 | UI/UX: 0
-----------------------------+------------------------------------
'''Motivation'''
For a large form grouping of fields is not just the pretty-rendering and
template-related issue and I believe there should be way to logically
group fields a form class definition. It would also be convenient to have
Django automatically render those group of fields, just as easy as it is
now to do `{{ form.as_p }}`.
'''Idea'''
The idea is to use existing and well-known conventions. Example:
{{{#!python
class PersonForm(forms.Form):
home_phone = CharField()
cell_phone = CharField()
first_name = CharField()
last_name = CharField()
class Meta:
fieldsets = (
(None, {
'fields': ('first_name', 'last_name'),
}),
("Phone numbers", {
'fields': ('cell_phone', 'home_phone'),
}),
)
}}}
Note usage of conventions already known to many users -- `Meta` class for
options (used in models and `ModelForm` already) and `fieldsets` tuple,
just like one in `ModelAdmin` options.
The idea is also not to break anything already working meaning being
backward compatible. Forms without fieldsets explicitly defined by user
should render normally.
Having a form defined as above user can easily use it in a template.
Example:
{{{
<form action="" method="post">
{{ form.as_table }}
<input type="submit" value="Send" />
</form>
}}}
Renders to:
{{{
<form action="" method="post">
<fieldset>
<table>
<tr>
<th><label for="id_first_name">First name:</label></th>
<td><input type="text" name="first_name"
id="id_first_name" /></td>
</tr>
<tr>
<th><label for="id_last_name">Last name:</label></th>
<td><input type="text" name="last_name" id="id_last_name"
/></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>Phone numbers</legend>
<table>
<tr>
<th><label for="id_cell_phone">Cell phone:</label></th>
<td><input type="text" name="cell_phone"
id="id_cell_phone" /></td>
</tr>
<tr>
<th><label for="id_home_phone">Home phone:</label></th>
<td><input type="text" name="home_phone"
id="id_home_phone" /></td>
</tr>
</table>
</fieldset>
<input type="submit" value="Send" />
</form>
}}}
Which I believe is a good default behavior. Other examples:
{{{
<form action="" method="post">
{% for fieldset in form.fieldsets %}
<fieldset>
{{ fieldset.legend_tag }}
<table>
{{ fieldset.as_table }}
</table>
</fieldset>
{% endfor %}
<input type="submit" value="Send" />
</form>
}}}
{{{
<form action="" method="post">
{% for fieldset in form.fieldsets %}
<fieldset>
{{ fieldset.legend_tag }}
<ul>
{% for field in fieldset %}
<li>
{{ field.label_tag }}
{{ field }}
</li>
{% endfor %}
</ul>
</fieldset>
{% endfor %}
<input type="submit" value="Send" />
</form>
}}}
{{{
<form action="" method="post">
{% for fieldset in form.fieldsets %}
<fieldset>
{{ fieldset.legend_tag }}
<ul>
{% for field in fieldset.visible_fields %}
<li>
{{ field.label_tag }}
{{ field }}
</li>
{% endfor %}
<li class="super-hidden">
{% for field in fieldset.hidden_fields %}
{{ field }}
{% endfor %}
</li>
</ul>
</fieldset>
{% endfor %}
<input type="submit" value="Send" />
</form>
}}}
'''Implementation'''
Yeah, there's a patch. Short description of implementation for those
afraid of reading the diff:
1. Creating `BaseFormOptions` class, similar to this already present in
`ModelForm` class (for defining model for form). `ModelFormOptions` now
subclasses it. `BaseFormMetaclass` now handles options-related stuff.
(note that this behavior may be used in future for other form options)
2. Separating all rendering from `Form` class to a new one - `Fieldset`.
Form not having any fieldsets defined uses the single, dummy fieldset for
all its fields.
3. No editing any of already existing tests. Everything should be backward
compatible.
4. Providing some tests for new behavior - form options and fieldsets.
5. Providing some documentation. Unfortunately my English skills are, as
you see, not that impressive, so it definitely need some touch. Now it's
more like set of examples.
'''Patch'''
Patch is attached. You can read it on Trac here or on my Django github
fork: https://github.com/mikoskay/django/compare/master...form-fieldsets
--
Ticket URL: <https://code.djangoproject.com/ticket/17301>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en.