AskhatOmarov
AskhatOmarov

Reputation: 39

grouping fields in django form

I want to render form grouping fields. Form actually is created dynamically according to incoming dictionary

for f in settings.FORM_BIG_FIELDS:
        self.fields[f['id']] = eval(f['type'])(label=f['label'], required=f.get('required', True))
        self.fields[f['id']].groupp = f.get('group', 1)

groupp attribute means appropriate group, then I try to render it like

{% regroup form.fields.values by groupp as field_group %}
    {% for group in field_group %}
    <div class="group_{{ group.grouper }}">
            {% for field in group.list %}
            <p>
                {{ field.all }}
                {{ field }}
            </p>
            {% endfor %}
    </div>
    {% endfor %}

But as output I get the following

<django.forms.fields.CharField object at 0xb527388c>
<django.forms.fields.IntegerField object at 0xb52738ec>
<django.forms.fields.ChoiceField object at 0xb527394c>

I have read that these are not the same as BoundField object. How to render fields or is there any other better approaches to group fields?

Upvotes: 0

Views: 4484

Answers (3)

raf1979
raf1979

Reputation: 1

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.

Upvotes: 0

EarlyCoder
EarlyCoder

Reputation: 1313

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 %}

Upvotes: 0

Odif Yltsaeb
Odif Yltsaeb

Reputation: 5666

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.

Upvotes: 1

Related Questions