Custom Save Method for Django Formset Item

Django formsets are pretty great… once you figure out how to use them. Here is a pretty good tutorial.

I was using the inlineformset_factory function:

inlineformset_factory(container_model, item_model)

in this case the function automagically creates a modelform for each item. If you want to alter that form, you can create a form and send it as a keyword:

inlineformset_factory(container_model, item_model, form=item_form)

but what if you need to change the form’s save method? In my case, my model had a field that I wanted to have the system set rather than the user. So I excluded it from the form and planned to add it in the form save method. The problem was the item needs to set a foreign key to the container model. How does that foreign key get set?

The answer is the save method is called with commit=False. All I had to do was set the field and pass the unsaved object back. Like this:

class ItemForm(forms.ModelForm):
    class Meta:
        model = models.Item
        exclude = ('myfield',)

    def save(self, *args, **kwargs):
        # Commit is already set to false
        obj = super(ItemForm, self).save(*args, **kwargs)
        obj.myfield = 3
        return obj