I run into this often:
I want to hide the default delete box in formsets and delete the instance of an object if a certain field is cleared in the each form of the formset.
The typical problem is that, either validation gets in the way or this breaks the blank form detection and starts adding all forms ( even blank extra ) when the formset is saved.
Here is the solution I found:
This code creates a model formset, ensures it validates by permitting a blank field, and then on save determines which objects to delete and which forms to save.
TaskFormset = inlineformset_factory(User, FAQ, extra=3, can_delete=False, exclude=('user', 'answer',))
formset = TaskFormset(request.POST, request.FILES, instance=user)
for form in formset:
form.fields['question'].required = False
// later when performing the formset save
for form in formset:
if form.instance.pk and form.cleaned_data['question'].strip() == '':
form.instance.delete()
elif form.cleaned_data:
form.save()
There's a method on BaseFormSet
called _should_delete_form
which makes it easy to automatically delete an instance based on your own criteria, however it's a "private" method so not sure about future support. You also need to save the formsets by calling formset.save()
.
In the example below it will delete a row if all the fields
values evaluate to false values.
class MyFormSet(forms.BaseInlineFormSet):
def _should_delete_form(self, form):
"""Return whether or not the form should be deleted."""
if form.cleaned_data.get(forms.formsets.DELETION_FIELD_NAME):
return True # marked for delete
fields = ('name', 'question', 'amount', 'measure', 'comment')
if not any(form.cleaned_data[i] for i in fields):
return True
return False
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With