GSoC Task 6 -- Edit Only mode for ModelFormset

About the task

There was no right way in which we can use ModelFormset for just editing a set of models without creating or affecting any other model. Few workarounds were present, but none produces the desired behavior. For e.g. one can argue that setting extra_form = 0 , max_num = 0 & validate_max = True will work. But if by some way the POST request is edited, and a different pk value that doesn’t appear in the queryset is sent, it will create a new model object, which is not desirable.

What I did ??

So this issue was solved by adding an extra parameter edit_only in the BaseModelFormSet class. This disabled the call to save_new_objects() method, thus ensuring no new object is created. And also one can now pass a list of pk values to the BaseFormSet while creating an object of formset so that only the pk values from that list can be edited, thus acting as a security feature so that no one can edit the POST request and affect the database.

This was a pretty straight-forward task and didn’t take me more than a week to complete this. And after doing development in Django for more than two months, this was done in a blink of an eye :).

Technical description of the task

The problem Statement from a technical point of view was simple enough. Just add an extra check before creating a new model. If that parameter is set, don’t create any new models.

Here is the snippet of code which I added:

def save(self, commit=True):
    """
    Save model instances for every form, adding and changing instances
    as necessary and return the list of instances.
    """
    if not commit:
        self.saved_forms = []

        def save_m2m():
            for form in self.saved_forms:
                form.save_m2m()
        self.save_m2m = save_m2m
    if not self.edit_only:
        return self.save_existing_objects(commit) + self.save_new_objects(commit)
    else:
        return self.save_existing_objects(commit)

Notice how the edit_only parameter blocks the new objects from being created.

References

Ticket – #26142
PR – #11580