wobbily_col
wobbily_col

Reputation: 11891

Django Model Formsets, change position of delete option

I have a ModelFormset in Django.

In the template I iterate through the forms, then iterate through each field in the form (I use it for two different models).

{%for form in formset %}
    <tr class='row{% cycle '2' '1' %}'>

        {% for hiddenfield in form.hidden_fields%}
           {{ hiddenfield }}
        {% endfor %}


        {% for field in form.visible_fields %}
            <td>{{ field.errors}}{{ field }}</td>
        {% endfor %}
        </tr>
{% endfor%}

I have added the can_delete=True to the formset_factory, and now I get the delete checkbox at the far right.

Is there any way to put this at the left and still iterate through the other form fields as before? Is there any way of making this the first form field when I iterate through the fields?

Upvotes: 2

Views: 819

Answers (2)

Dot Momo
Dot Momo

Reputation: 1

I kept getting "TypeError: can only concatenate list (not "ItemsView") to list" with seddonym's suggested code above. In Python 3, there is an easier way to move an item in OrderedDict to the front. So the following code did the job for me:

class BaseMyModelFormSet(BaseFormSet):

    def add_fields(self, form, index):
        super(BaseMyModelFormSet, self).add_fields(form, index)
        # Move the delete field to the front end
        form.fields.move_to_end('DELETE', last=False)

Upvotes: 0

seddonym
seddonym

Reputation: 17229

You can override the add_fields method of the BaseFormSet, moving the delete field to the front, like so:

from collections import OrderedDict
from django import forms
from django.forms.formsets import BaseFormSet, formset_factory
from .models import MyModel


class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel


class BaseMyModelFormSet(BaseFormSet):

    def add_fields(self, form, index):
        super(BaseMyModelFormSet, self).add_fields(form, index)
        # Pop the delete field out of the OrderedDict
        delete_field = form.fields.pop('DELETE')
        # Add it at the start
        form.fields = OrderedDict(
                      [('DELETE', delete_field)] + form.fields.items())


MyModelFormSet = formset_factory(MyModelForm, BaseMyModelFormSet,
                             extra=2, can_delete=True)

Upvotes: 3

Related Questions