I’m Lazier Then Django Forms

by Hose-A S-Warez •  Published 17 Jan 2009

When I started to learn django, i fell in love with django forms, or newforms as it was called then. It made writing forms a lot more enjoyable. So like many relationship, it started out great, we, (me and django forms), were having a great time together, having fun spending a lot of time together, great. Then we started to get serious and that’s when things became more complicated.

I found myself using copy and paste a lot, from one form to another form. Sure it did the job, but it required more effort then I wanted to give. I had to give it a couple looks each time to ensure everything was correct. It got tedious, and i have to blame django forms for this. It has spoiled me, making things to easy to use. I can’t imagine trying to write out forms like I once did in .NET.

So as our relationship continued we found our selves in the same cycle, everything the same. But I wanted more, I wanted to us to be in love again. Like we were when we first meet.

Solution - Form Options

class FormOptions():
    """
    FormOptions class gives Form extra properties 
    so we can build a generic form template and
    relieve the need to re-create a form, even more
    lazier then newforms.
    """
    (id, method, action, enctype, accept,
    accept_charset, cssclass, has_reset,
    include_help_text, submit_label, reset_label) = (None, None, 
    None, None, None, None, None, None, None, None, None)

    def __new__(self, id=None, method='POST', action='.', enctype=None, accept=None,
                 accept_charset=None, cssclass='form_wrapper', has_reset=False,
                 include_help_text=False, submit_label='Submit', reset_label='Reset'):

        if not action:
            raise ValueError('Action is not defined.')

        (self.id, self.method, self.action, self.enctype,
         self.accept, self.accept_charset, self.cssclass,
         self.has_reset, self.submit_label, self.reset_label,
         self.include_help_text) = (id, method, action, enctype,
         accept, accept_charset, cssclass,
         has_reset, submit_label, reset_label,
         include_help_text)

Very simple, yes. But that’s not all, I also made a template tag…

@register.inclusion_tag('core/form.html')
def build_form(form):
    return { 'form': form }

And then the forms.html template…

{% if form.options %}
    <div{% if form.options.cssclass %} class="{{ form.options.cssclass }}"{% endif %}>
        <form action="{{ form.options.action }}"
            {% if form.options.id %} id="{{ form.options.id }}"{% endif %}
            {% if form.options.method %} method="{{ form.options.method }}"{% endif %}
            {% if form.options.type %} type="{{ form.options.type }}"{% endif %}
            {% if form.options.enctype %} enctype="{{ form.options.enctype }}"{% endif %}
            {% if form.options.accept %} accept="{{ form.optons.accept }}"{% endif %}
            {% if form.options.accept_charset %} accept_charset="{{ form.options.accept_charset }}"{% endif %}>
{% endif %}
{% if form.errors %}
        <div class="error">
           There was errors, please correct them and try again.
        </div>
      {% endif %}
      {% if form.non_field_errors %}
          {% for error in form.non_field_errors %}
                <div class="error">{{ error }}</div>
          {% endfor %}
      {% endif %}
{% for field in form %}
    <fieldset>
        {% if field.errors %}
            <div class="error">{{ field.errors }}</div>
        {% endif %}
        {{ field.label_tag }} {{ field }}
        {% if form.options and form.options.include_help_text %}
            <div class="field_help">{{ field.help_text }}</div>
        {% endif %}
    </fieldset>
{% endfor %}
{% if form.options %}
    <fieldset>
        <input{% if form.options.submit_id %} id="{{ form.options.submit_id }}"{% endif %} type="submit" name="submit" value="{{ form.options.submit_label }}" />
        {% if form.options.has_reset %}
            <input{% if form.options.reset_id %} id="{{ form.options.reset_id }}"{% endif %} type="reset" name="reset" value="{{ form.options.reset_label }}" />
        {% endif %}
    </fieldset>
{% endif %}
{% if form.options %}
        </form>
    </div>
{% endif %}

The last step is to add the FormOptions class to your form like below…

class paste_form(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput(), required=False, 
                        help_text='Optional, password protect this code.')
    type = forms.ChoiceField(choices=code_types, 
                        help_text=mark_safe(code_type_help_text))

    options = FormOptions()

And anywhere I need a form on my page, it will look like this…

{% load defaulttags %}
{% build_form form1 %}
{% build_form form2 %}

And so, me and django forms are now back in love.

blog comments powered by Disqus