How to avoid admin.E111 error in Django 1.9.2?

Question:

Up until Django 1.8.x I had this code in my admin.py file:

class MyClassAdmin(admin.ModelAdmin):
    # ...
    list_display = ('field1', 'field2', 'field3')

    def __init__(self, *args, **kwargs):
        super(MyClassAdmin, self).__init__(*args, **kwargs)
        self.list_display_links = (None, )

This was meant to disable the link on the rows of the Model when the users opened it. I need this because this refers to a read-only table and I don’t want users to be able to even edit entries.

Recently, I upgraded to Django 1.9.2, and this code is currently returning an error:

django.core.management.base.SystemCheckError: SystemCheckError: System
check identified some issues:

ERRORS: <class ‘myapp.admin.MyClassAdmin’>: (admin.E111) The value of
‘list_display_links[0]’ refers to ‘None’, which is not defined in
‘list_display’.

As per the Django docs, this is:

admin.E111: The value of list_display_links[n] refers to , which is not defined in list_display.

This is quite vague and doesn’t explain how to handle non-string values such as None.

How can I modify this piece of code so I can overwrite the list_display_links attribute in the __init__ function?

Asked By: nKn

||

Answers:

The docs for list_display_links say that you should use None if you do not want to display any links. You are returning a tuple, which means that Django expects each item in the tuple to be a field in list_display. Since None is not a field, you get the error from the checks framework.

As an aside, it’s not recommended to set self.list_display_links in the model admin’s __init__ method. It would be better to set list_display_links on the class.

class MyClassAdmin(admin.ModelAdmin):
    ...
    list_display = ('field1', 'field2', 'field3')
    list_display_links = None

Or, if you need to change it dynamically, then override get_list_display_links.

class MyClassAdmin(admin.ModelAdmin):
    ...
    list_display = ('field1', 'field2', 'field3')

    def get_list_display_links(request, list_display):
        if condition():
            return None
        else:
            return list_display
Answered By: Alasdair

You should assign None instead of (None, ) to self.list_display_links as shown below:

class MyClassAdmin(admin.ModelAdmin):
    # ...
    list_display = ('field1', 'field2', 'field3')

    def __init__(self, *args, **kwargs):
        super(MyClassAdmin, self).__init__(*args, **kwargs)
        # self.list_display_links = (None, )
        self.list_display_links = None
                                 # ↑ Here

And, you will get the same error if assigning (None, ) to list_display_links as shown below:

class MyClassAdmin(admin.ModelAdmin):
    # ...
    list_display = ('field1', 'field2', 'field3')
    list_display_links = (None, ) # Here

So, you should assign None instead of (None, ) to list_display_links as shown below:

class MyClassAdmin(admin.ModelAdmin):
    # ...
    list_display = ('field1', 'field2', 'field3')
    # list_display_links = (None, )
    list_display_links = None
                        # ↑ Here

In addition, I got the similar error below:

ERRORS: <class ‘store.admin.PersonAdmin’>: (admin.E111) The value of
‘list_display_links[1]’ refers to ‘last_name’, which is not defined in
‘list_display’.

When "last_name" is not assigned to list_display but assigned to list_display_links as shown below:

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    list_display = ("first_name",)      # ↓ Here
    list_display_links = ("first_name", "last_name")

So, I assigned "last_name" to list_display then the error above was solved:

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin): # ↓ Here
    list_display = ("first_name", "last_name")      
    list_display_links = ("first_name", "last_name")
Answered By: Kai – Kazuya Ito