I have a model that is being shared across many different forms. An ugly side effect of this was that if I ever forgot to ensure that the HTML rendered contained *exactly* the fields defined in the form, django would overwrite the values.
Here’s a mixin that you can add to any ModelForm which will only update values.
Note that this still allows users to update a model field explicitly with a blank.
from django.forms.models import model_to_dict
from django import forms
class OverwriteOnlyModelFormMixin(object):
'''
Delete POST keys that were not actually found in the POST dict
to prevent accidental overwriting of fields due to missing POST data.
'''
def clean(self):
cleaned_data = super(OverwriteOnlyModelFormMixin, self).clean()
for field in cleaned_data.keys():
if self.prefix is not None:
post_key = '-'.join((self.prefix, field))
else:
post_key = field
if post_key not in self.data:
# value was not posted, thus it should not overwrite any data.
del cleaned_data[field]
# only overwrite keys that were actually submitted via POST.
model_data = model_to_dict(self.instance)
model_data.update(cleaned_data)
return model_data
Thanks, save time for me!