Ignoring empty forms in a formset

9,223 views
Skip to first unread message

Martin Tiršel

unread,
Apr 22, 2012, 12:44:53 PM4/22/12
to django...@googlegroups.com
Hello,

I have a formset and some JavaScript to add more forms into this formset. In a view, I iterate through the formset saving (not a ModelForm just Form with save method) each form:

for form in formset:
    form.save()

But I want to ignore empty forms that were added by JavasScript and not removed. How can I do this?

Thanks,
Martin

Martin Tiršel

unread,
Apr 23, 2012, 10:42:53 AM4/23/12
to django...@googlegroups.com
Nobody knows how to ignore empty forms in a formset? I have to write some custom method on a form that checks all fields and returns False if any of the fields is filled or is there any other solution?

Martin

Marcin Tustin

unread,
Apr 23, 2012, 10:48:29 AM4/23/12
to django...@googlegroups.com
You will want to edit the management form values on the client side, as described in the documentation.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To view this discussion on the web visit https://groups.google.com/d/msg/django-users/-/Y_DfzKjYiYwJ.

To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.



--
Marcin Tustin
Tel: 07773 787 105

Martin Tiršel

unread,
Apr 25, 2012, 2:33:10 AM4/25/12
to django...@googlegroups.com
I am doing that:

<input id="id_form-TOTAL_FORMS" type="hidden" value="2" name="form-TOTAL_FORMS">
<input id="id_form-INITIAL_FORMS" type="hidden" value="0" name="form-INITIAL_FORMS">
<input id="id_form-MAX_NUM_FORMS" type="hidden" name="form-MAX_NUM_FORMS">

When I add a form to formset, I increase form-TOTAL_FORMS. But this doesn't affect processing of empty forms.

Martin

Tom Evans

unread,
Apr 25, 2012, 5:03:49 AM4/25/12
to django...@googlegroups.com

You don't show much of your code, but I presume you have called
formset.is_valid() at this point?

If so, this pattern is pretty canonical:

if formset.is_valid():
for form in formset:
if form.is_valid() and not form.empty_permitted:
form.save()

Extra forms in a formset are all instantiated with empty_permitted=True.

There are other things to be aware of though. This logic will not take
into account deleted forms etc, which is why there is a
BaseModelFormSet with the right behaviour baked into it's save()
method.

Cheers

Tom

Martin Tiršel

unread,
Apr 25, 2012, 7:55:15 AM4/25/12
to django...@googlegroups.com
I am using class based views and my code is:

class PayOrdersView(AdminFormSetView):
    form_class = PayOrderForm
    template_name = 'internal/orders/pay_orders_form.html'
    active_item = 'order_pay_orders'
    context_formset_name = 'pay_orders_formset'
    extra = 2

    def formset_valid(self, formset):
        logger.debug('Executing formset_valid')
        for form in formset:
            logger.debug('Is empty: %s' % form.empty_permitted)
            form.save()
        return super(PayOrdersView, self).formset_valid(formset)


formset_valid method is called after formset.is_valid(). I start with 2 empty forms, I insert into first form order number and the second form stays empty. After I submit, I get:

[2012-04-25 13:42:07,776] DEBUG [31099 140249342375680] [project.internal.mixins:304] Processing POSTed form
[2012-04-25 13:42:07,778] DEBUG [31099 140249342375680] [project.internal.forms:29] Cleaning order_number
[2012-04-25 13:42:07,837] DEBUG [31099 140249342375680] [project.internal.mixins:307] Formset is valid
[2012-04-25 13:42:07,842] DEBUG [31099 140249342375680] [project.internal.views:93] Executing formset_valid
[2012-04-25 13:42:07,843] DEBUG [31099 140249342375680] [project.internal.views:95] Is empty: True
[2012-04-25 13:42:07,843] DEBUG [31099 140249342375680] [project.internal.forms:54] Saving PayOrderForm
[2012-04-25 13:42:09,914] DEBUG [31099 140249342375680] [project.internal.views:95] Is empty: True
[2012-04-25 13:42:09,914] DEBUG [31099 140249342375680] [project.internal.forms:54] Saving PayOrderForm

So both forms have empty_permitted == True. Management form in time of submit looks so:

<input id="id_form-TOTAL_FORMS" type="hidden" value="2" name="form-TOTAL_FORMS">
<input id="id_form-INITIAL_FORMS" type="hidden" value="0" name="form-INITIAL_FORMS">
<input id="id_form-MAX_NUM_FORMS" type="hidden" name="form-MAX_NUM_FORMS">

Thanks, Martin

Tom Evans

unread,
Apr 25, 2012, 8:35:20 AM4/25/12
to django...@googlegroups.com
Hmm. Internally, model formsets do this differently - they are aware
of which forms are extra forms, and which forms are existing forms.

New forms will have form.empty_permitted=True, unmodified forms will
return True from form.has_changed(). This should be enough to skip
over blank new forms.

Cheers

Tom

> --
> You received this message because you are subscribed to the Google Groups
> "Django users" group.
> To view this discussion on the web visit

> https://groups.google.com/d/msg/django-users/-/aKliGdMNqGwJ.

Martin Tiršel

unread,
Apr 26, 2012, 2:25:42 AM4/26/12
to django...@googlegroups.com
Thanks, form.has_changed() seems to be the way. But I don't understand the empty_permitted attribute, it is usable only with ModelForm? I am using the formset only for mass form processing not for inserting/updating models.

Martin

Carlos Jordán

unread,
Apr 15, 2017, 5:25:28 PM4/15/17
to Django users
its works
Reply all
Reply to author
Forward
0 new messages