[Answer]-Grouping fields in django form

1👍

If you do not want use any additional libraries, then the most easy solution is to render them manually, i would say. Otherwise you will just spend alot of time repeating the functionality of the library i copied as comment to your post.

There is always the case that things should be DRY. But we build websites for the users and user cares little about how the form rendering in template is done. For this reason we have often created form templates manually like this:

<div class="something">
{{ form.fieldname.label_tag }}{{ form.fieldname }}
</div>

Easyest way to organise it saving you some time. And in my opinion it is not that bad either, since this is not very common when you need fields organised by fieldsets.

0👍

I know this question is rather old, but I am sure there are still people who can benefit from a simple solution:

Say you have a group name and list of members. You can define a self.fieldset in your form’s init to be a dictionary of {‘group_1’: [‘member_1’, ‘member_2’, … ], … }. Once you attach this to the form, you can pass it to views and from there to the template:

In forms.py:

class MyForm:
    def __init__(self, current_user, *args, **kwargs):    
        super(YourForm, self).__init__(*args, **kwargs)
        self.field['group'].queryset = Group.objects.filter(user = current_user)
        ...

In views.py:

form = self.Form(current_user)
the_fieldsets = form.fieldset

c = {'form': search_form,
     'fieldsets':  the_fieldsets }

In your template:

{% for field in form %}
            <tr>
                <td>{{field.label_tag}}</td>
                {% if field.name == 'group' %}
                <td>

                    <select id='{{field.id}}' name='{{field.name}}'>
                        {% for k,v in fieldsets.items %}
                        <optgroup label = {{k.name}}>
                            {% for val in v %}
                                <option name='{{val}} value = {{val.id}}> {{val.name}} </option>  # Note that the select needs to return 'id', so value has to be {{val.id}}
                            {% endfor %}
                        </optgroup>
                        {% endfor %}
                    </select>
                </td>                       
                {% else %}
                    <td>{{field}}</td>
                {% endif %}

                <td>{{field.help_text}}</td>
                <td>{{field.errors}}</td>
            </tr>
        {% endfor %}

0👍

The secret is to use :

self[name]

in the form object. So you can use it in any dictionary like :

def __init__(self, *args, **kwargs):
    super().__init__( *args, **kwargs)
    self.fields['field01'] = forms.IntegerField()
    self.groupe1 = {'foo' : self['field01']}

and now it will render correctly in the template. But in the above code you’ll also have to deal with the initial and data value of the field. But it is an other question.

Leave a comment