Question

I have a Django model with a created_on field set to editable=False. This is the correct behavior because I have also set auto_now=True and per the documentation:

"As currently implemented, setting auto_now or auto_now_add to True will cause the field to have editable=False and blank=True set."

Using the admin, you can define any fields you have set to editable=False as readonly_fields in the ModelAdmin and everything will work as expected (i.e. the fields will show up in the form, but they will be grayed out).

However, when working with a ModelFormSet in an app (i.e. not the admin), I cannot figure out how to show the created_on field in the forms. Per the documentation:

"Django applies the following rule: if you set editable=False on the model field, any form created from the model via ModelForm will not include that field."

Does anybody know of a way to override/circumvent that behavior?

I would rather not set editable=True because it is a constraint I want to maintain at the most basic level. I probably can't set it to True anyways if I'm using auto_now=True.

Was it helpful?

Solution

After hours of searching for a solution I finally figured it out. It is possible to get and populate data for a field which has editable=false by:

  1. Adding the field definition to the ModelForm class
  2. Adding an __init__ method which instantiates the value of the field
  3. Adding adding the field to the fields tuple in the Class Meta definition of the ModelForm class

For example:

class MyModelForm(forms.ModelForm):
    created_on = forms.DateField(widget=forms.DateInput(attrs={'readonly': 'readonly'}))

    def __init__(self, *args, **kwargs):
        super(MyModelForm, self).__init__(*args, **kwargs)

        if self.instance:
            if not self.initial.get('created_on'):
                self.initial['created_on'] = self.instance.created_on

    class Meta:
        model = MyModel
        fields = ('field1', 'field2', 'etc', 'created_on')
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top