Django ModelForm and Conditionally Disabled (Readonly) Fields

I ran into a use case today that required a model form to have some fields disabled (readonly), but only when a certain condition was met (specifically when a property of the model was set to true) . Since the model form is used with the fields both enabled and disabled, simply duplicating the model form and removing the necessary fields wasn’t an option (plus that’s not exactly DRY now is it).

The solution ended up being quite simple. First, you’ll need to override the clean method for each field that needs to be disabled within your model form class:

# the following fields can only be updated when the is_disabled property is set to false
def clean_field_1(self):
if self.instance.is_disabled:
return self.instance.field_1
return self.cleaned_data.get('field_1')
def clean_field_2(self):
if self.instance.is_disabled:
return self.instance.field_2
return self.cleaned_data.get('field_2')

view raw

hosted with ❤ by GitHub

The clean field method simply checks the is_disabled property and if it’s true, returns the existing field data. It only returns the new submitted data, pulled from cleaned_data, if is_disabled is false.

The second part of the solution is to set the field to readonly in your template. Note that you need to use readonly rather than disabled as the field won’t actually be submitted if set to disabled (more info on this here). This will cause Django to throw a missing field error before the clean field method ever runs.

You can add the necessary html to the form field via the widget’s attributes property:

modelform.fields['field_1'].widget.attrs['readonly'] = True

view raw

hosted with ❤ by GitHub

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s