Django admin: How to display a field that is marked as editable=False' in the model?

DjangoDjango Admin

Django Problem Overview


Even though a field is marked as 'editable=False' in the model, I would like the admin page to display it. Currently it hides the field altogether.. How can this be achieved ?

Django Solutions


Solution 1 - Django

Use Readonly Fields. Like so (for django >= 1.2):

class MyModelAdmin(admin.ModelAdmin):
    readonly_fields=('first',)

Solution 2 - Django

Update

This solution is useful if you want to keep the field editable in Admin but non-editable everywhere else. If you want to keep the field non-editable throughout then @Till Backhaus' answer is the better option.

Original Answer

One way to do this would be to use a custom ModelForm in admin. This form can override the required field to make it editable. Thereby you retain editable=False everywhere else but Admin. For e.g. (tested with Django 1.2.3)

# models.py
class FooModel(models.Model):
    first = models.CharField(max_length = 255, editable = False)
    second  = models.CharField(max_length = 255)

    def __unicode__(self):
        return "{0} {1}".format(self.first, self.second)

# admin.py
class CustomFooForm(forms.ModelForm):
    first = forms.CharField()

    class Meta:
        model = FooModel
        fields = ('second',)

class FooAdmin(admin.ModelAdmin):
    form = CustomFooForm

admin.site.register(FooModel, FooAdmin)

Solution 3 - Django

Your read-only fields must be in fields also:

fields = ['title', 'author', 'content', 'published_date', 'updated_date', 'created_date']
readonly_fields = ('published_date', 'updated_date', 'created_date')

Solution 4 - Django

You could also set the readonly fields as editable=False in the model (django doc reference for editable here). And then in the Admin overriding the get_readonly_fields method.

# models.py
class MyModel(models.Model):
  first = models.CharField(max_length=255, editable=False)

# admin.py
class MyModelAdmin(admin.ModelAdmin):
  def get_readonly_fields(self, request, obj=None):
    return [f.name for f in obj._meta.fields if not f.editable]

Solution 5 - Django

With the above solution I was able to display hidden fields for several objects but got an exception when trying to add a new object.

So I enhanced it like follows:

class HiddenFieldsAdmin(admin.ModelAdmin):
def get_readonly_fields(self, request, obj=None):
    try:
        return [f.name for f in obj._meta.fields if not f.editable]
    except:
        # if a new object is to be created the try clause will fail due to missing _meta.fields
        return ""

And in the corresponding admin.py file I just had to import the new class and add it whenever registering a new model class

from django.contrib import admin
from .models import Example, HiddenFieldsAdmin

admin.site.register(Example, HiddenFieldsAdmin)

Now I can use it on every class with non-editable fields and so far I saw no unwanted side effects.

Solution 6 - Django

You can try this

@admin.register(AgentLinks)
class AgentLinksAdmin(admin.ModelAdmin):
    readonly_fields = ('link', )

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGabiMeView Question on Stackoverflow
Solution 1 - DjangotbackView Answer on Stackoverflow
Solution 2 - DjangoManoj GovindanView Answer on Stackoverflow
Solution 3 - DjangogabrielView Answer on Stackoverflow
Solution 4 - DjangoraphodnView Answer on Stackoverflow
Solution 5 - DjangoSchnurcksView Answer on Stackoverflow
Solution 6 - DjangoBercoveView Answer on Stackoverflow