Задать вопрос

Тел: +7 965 3737 888





BetterForm with fieldsets and row_attrs

<p><strong>NOTE</strong>: Further development of this snippet will take place in the <a href="http://launchpad.net/django-form-utils">django-form-utils</a> project.</p>
<p>This snippet provides BetterForm and BetterModelForm classes which are subclasses of django.forms.Form and django.forms.ModelForm, respectively.  BetterForm and BetterModelForm allow subdivision of forms into fieldsets which are iterable from a template, and also allow definition of row_attrs which can be accessed from the template to apply attributes to the surrounding container of a specific form field.</p>
<p>It's frequently said that a generic form layout template is a pipe dream and in "real usage" it's necessary to manually layout forms, but in my experience the addition of fieldsets and row_attrs, plus a competent CSS designer, make it possible to create a generic template that can render useful production form markup in 95+% of cases.</p>
class MyForm(BetterForm):
    one = forms.CharField()
    two = forms.CharField()
    three = forms.CharField()
    class Meta:
        fieldsets = (('main', {'fields': ('two',), 'legend': ''}),
                     ('Advanced', {'fields': ('three', 'one'),
                                   'description': 'advanced stuff'}))
        row_attrs = {'one': {'style': 'display: none'}}

<p>Then in the template:</p>
{% if form.non_field_errors %}{{ form.non_field_errors }}{% endif %}
{% for fieldset in form.fieldsets %}
  &lt;fieldset class="fieldset_{{ fieldset.name }}"&gt;
  {% if fieldset.legend %}
    &lt;legend&gt;{{ fieldset.legend }}&lt;/legend&gt;
  {% endif %}
  {% if fieldset.description %}
    &lt;p class="description"&gt;{{ fieldset.description }}&lt;/p&gt;
  {% endif %}
  {% for field in fieldset %}
    {% if field.is_hidden %}
      {{ field }}
    {% else %}
      &lt;li{{ field.row_attrs }}&gt;
        {{ field.errors }}
        {{ field.label_tag }}
        {{ field }}
    {% endif %}
  {% endfor %}
{% endfor %}

Вопрос полезен? Да0/Нет0

Ответы (5):

Ответ полезен? Да0/Нет0

Thanks for this... however, there is a small syntax error: the "ls" on line 42

Ответ полезен? Да0/Нет0

Oh, of course, you're right.

Ответ полезен? Да0/Нет0

Hi, it's the logical consequence of the code in line 67 (i.e. put all fields in one "dummy" fieldset if none are defined).

My use-case is simply a generic template that assumes all forms have formsets.

Ответ полезен? Да0/Нет0

Thanks for the feedback. Not sure why I should lie about the number of fieldsets when there aren't any. If you don't define any fieldsets, you should loop over "field in form" normally, not "fieldset in form.fieldsets".

Can you say more about the usage case that makes this a problem?

Ответ полезен? Да0/Нет0

Hi. Nice work, there is a small bug thoug:

in FieldsetCollection _ len _ should be defined as:

def __len__(self):
    return len(self.fieldsets) or 1

otherwise the "for" tag for example wont enter the loop if there are no formsets defined since it seems to check the length of the iterable before starting the loop.