Django Form rendering helper tags
Switch branches/tags
Pull request Compare This branch is 189 commits behind funkybob:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


Django Form rendering helper tags


It's fairly well accepted, now, that having the form rendering decisions in your code is less than idea.

However, most template-based solutions wind up being slow, because they rely on many templates.

Formulation works by defining all the widgets for your form in a single template.


First, write a template where each block is a way to render a field.

We'll start with a simple one, with one hardy, general purpose field block. Let's call it "mytemplate.form":

{% block basic %}
{% if not nolabel %}
<label for="{{ field.auto_id }}" {% if field.required %}class="required"{% endif %}> {{ label|default:field.label }} </label>
{% endif %}
<input type="{{ field_type|default:"text" }}" name="{{ field.html_name }}" id="{{ field.auto_id }}" value="{{ field.value|default:"" }}" {% if field.errors %}class="error"{% endif %} />
{{ field.help_text }}
{% endblock %}

Then, in your own template:

{% load formulation %}

<form method="POST" ... >
{% form "mytemplate.form" %}
{% field "basic" %}
{% field "basic" nolabel=True %}
{% field "basic" form.baz type='email' %}
{% endform %}

Yep, it's that simple.

The {% form %} tag loads the template, and puts its blocks in a dict in context, called 'widgets'.

Each time you use the {% field %} tag, it renders the block.

Want more complex field types:

{% block TypedChoiceField %}
{% if not nolabel %}
<label for="{{ }}" {% if field.required %}class="required"{% endif %}> {{ field.label }} </label>
{% endif %}
<select name="{{ field.html_name }}" id="{{ field.auto_id }}" {% if field.errors %}class="error"{% endif %}>
{% for option_value, option_label in field.field.choices %}
<option value="{{ option_value }}" {% if field.value == option_value|safe %}selected="selected"{% endif %}>{{ option_label }}</option>
{% endfor %}
{{ field.help_text }}
{% endblock %}

Also, you can pass multiple form fields as positional arguments, if your widget is written to render them.

{% field "multiwidget" field1 field1 .... %}

You can even use template inheritance, just as normal.


Also, to help with repeated block, there's the "use" tag.

{% use "other" foo="bar" baz=quux %}

It works just like include, but will use a block from the current widget template.


Thanks to kezabelle for the name! Thanks to bradleyayers for ideas on supporting multiple fields.