Skip to content

Instantly share code, notes, and snippets.

@mintchaos
Created November 24, 2009 03:20
Show Gist options
  • Save mintchaos/241596 to your computer and use it in GitHub Desktop.
Save mintchaos/241596 to your computer and use it in GitHub Desktop.
<li class="formrow formrow_{{ field.name }}{% if errors %} has_errors{% endif %}{% if not field.field.required %} optional{% else %} required{% endif %}">
<label for="{{ field.auto_id }}">{{ field.label }}{% if not field.field.required %}<em> (optional)</em>{% endif %}</label>
{{ errors }}
{{ field }}
<small class="help_text">{{ help_text }}</small>{{ hiddenfields }}
</li>
"""
This is only here temporarily until I have a chance to move it to GH and give it
attention. It's plumbing I'm stealing from myself. -- Xian
"""
from django import template
from django.forms import Form, BaseForm
from django.forms.forms import BoundField
from django.template import Context, Template, TemplateDoesNotExist
from django.template.loader import select_template
from django.utils.encoding import force_unicode
from django.utils.html import escape
from django.utils.safestring import mark_safe
register = template.Library()
@register.filter
def get_fields(form, field_names):
"""
Returns the named fields from a Form as a list of BoundFields. Usage:
{% for field in form|get_fields:"field1,field2,field3" %}
"""
fields = []
if not isinstance(form, BaseForm):
return fields
else:
field_names = field_names.split(',')
for name in field_names:
fields.append(BoundField(form, form.fields[name], name))
return fields
## the next couple of fuctions are messier than they should be but they work
def _get_field_context(bf, bf_errors, error_list_format=None):
"""A helper method for for setting up the context for for a field"""
form = bf.form
if bf.label:
label = escape(force_unicode(bf.label))
# Only add the suffix if the label does not end in punctuation.
# This should probably be in the label_tag method
if form.label_suffix:
if label[-1] not in ':?.!':
label += form.label_suffix
label = bf.label_tag(label) or ''
else:
label = ''
if bf.help_text:
help_text = bf.help_text
else:
help_text = u''
if error_list_format:
try:
bf_errors = force_unicode(getattr(bf_errors, error_list_format)())
except AttributeError:
bf_errors = force_unicode(bf_errors)
return {'errors': bf_errors, 'label': label, 'field': bf, 'help_text': help_text }
def form_output_filter_helper(form_or_field, template, error_list_format=None):
"Helper function for outputting HTML. Used by for form output filters"
output, hidden_fields, row_contexts = [], [], []
if isinstance(form_or_field, BoundField):
bf = form_or_field
form = form_or_field.form
bf_errors = form.error_class([escape(error) for error in bf.errors]) # Escape and cache in local variable.
row_contexts.append(_get_field_context(bf, bf_errors, error_list_format))
elif isinstance(form_or_field, BaseForm):
form = form_or_field
for bf in form:
bf_errors = form.error_class([escape(error) for error in bf.errors]) # Escape and cache in local variable.
if bf.is_hidden:
hidden_fields.append(unicode(bf))
else:
row_contexts.append(_get_field_context(bf, bf_errors, error_list_format))
else:
return form_or_field
if hidden_fields: # Insert any hidden fields in the last row.
str_hidden = u''.join(hidden_fields)
if row_contexts:
# Add hidden fields to the last row's context.
last_row = row_contexts[-1]
last_row['hidden_fields'] = str_hidden
output[-1] = last_row
else: # If there aren't any rows in the output, just append the hidden fields.
output.append(str_hidden)
if row_contexts:
if not isinstance(template, Template):
template = Template(template)
for row in row_contexts:
output.append(template.render(Context(row)))
return mark_safe(u'\n'.join(output))
@register.filter
def as_table(form_or_field):
"Returns this form rendered as HTML <tr>s -- excluding the <table></table>."
row = """<tr><td colspan="2">{{ errors }}</td></tr>
<tr><th>{{ label }}</th><td>{{ field }} {% if help_text %}<br>{{ help_text }}{% endif %} {{ hidden_fields }}</td></tr>"""
return form_output_filter_helper(form_or_field, row)
# This one shows off the template advantage in that it's easy to do things like
# add the field_name as a class to each row and adding a has_error class when appropriate
@register.filter
def as_ul(form_or_field):
"Returns this form rendered as HTML <li>s -- excluding the <ul></ul>."
row = """<li class="{{ field.name }}{% if errors %} has_errors"{% endif %}>
{{ errors }}{{ label }} {{ field }} {{ help_text }}{{ hiddenfields }}
</li>
"""
return form_output_filter_helper(form_or_field, row)
# This one shows off that you can pass a format type to the error list class
@register.filter
def as_p(form_or_field):
"Returns this form rendered as HTML <p>s."
row = """{{ errors }}
<p>{{ label }} {{ field }} {{ help_text }}{{ hiddenfields }}</p>"""
return form_output_filter_helper(form_or_field, row, 'as_text')
@register.filter
def as_template(form_or_field, templatename="forms/as_template.html"):
"""
Returns this form or field using the django template specified for each row.
Uses `forms/as_template.html` by default but can be passed one more more
template paths (comma separated) to render.
"""
templatenames = templatename.split(',')
try:
row_template = select_template(templatenames)
except TemplateDoesNotExist:
return ""
return form_output_filter_helper(form_or_field, row_template)
{{ form|as_template }}
{{ form.email|as_template }}
{% for field in form|get_fields:"name,email,phone" %}
{{ field|as_template }}
{% endfor %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment