I'm trying to use get_readonly_fields in a TabularInline class in Django:
class ItemInline(admin.TabularInline):
model = Item
extra = 5
def get_readonly_fields(self, request, obj=None):
if obj:
return ['name']
return self.readonly_fields
This code was taken from another StackOverflow question: Django admin site: prevent fields from being edited?
However, when it's put in a TabularInline class, the new object forms don't render properly. The goal is to make certain fields read only while still allowing data to be entered in new objects. Any ideas for a workaround or different strategy?
As others have added, this is a design flaw in django as seen in this Django ticket (thanks Danny W).
get_readonly_fields
returns the parent object, which is not what we want here.Since we can't make it readonly, here is my solution to validate it can't be set by the form, using a formset and a clean method:
Careful - "obj" is not the inline object, it's the parent. That's arguably a bug - see for example this Django ticket
As a workaround to this issue I have associated a form and a Widget to my Inline:
admin.py:
in Django 2.0:
forms.py
in widgets.py
older Django Versions:
forms.py
in widgets.py
This is still currently not easily doable due to the fact that obj is the parent model instance not the instance displayed by the inline.
What I did in order to solve this, was to make all the fields, in the inline form, read only and provide a Add/Edit link to a ChangeForm for the inlined model.
Like this
And then in the inline I will have something like this
Then in the ChangeForm I'll be able to control the changes the way I want to (I have several states, each of them with a set of editable fields associated).
You are on the right track. Update self.readonly_fields with a tuple of what fields you want to set as readonly.