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.