[Django]-Change list display link in django admin

37👍

The solution was to override the init and set the list_display_links to None e.g.

class FooModelAdmin(admin.ModelAdmin):
    fields = ('foo','bar')
    list_display = ('foo_link','bar')

    def foo_link(self,obj):
        return u'<a href="/foos/%s/">%s</a>' % (obj.foo,obj)
    foo_link.allow_tags = True
    foo_link.short_description = "foo"
    def __init__(self,*args,**kwargs):
        super(FooModelAdmin, self).__init__(*args, **kwargs)
        self.list_display_links = (None, )

38👍

I believe the correct way of doing it, is subclassing ChangeList and override the url_for_result method to create the correct change url you want.

Override the get_changelist in the admin.ModelAdmin subclass to return the new class:

from django.contrib.admin.views.main import ChangeList
from django.contrib.admin.util import quote

class FooChangeList(ChangeList):
    def url_for_result(self, result):
        pk = getattr(result, self.pk_attname)
        return '/foos/foo/%d/' % (quote(pk))

class FooAdmin(admin.ModelAdmin):
    def get_changelist(self, request, **kwargs):
        return FooChangeList
👤Fred

18👍

By default the first column of list display will be link to the admin edit page. If you want another column or columns to be that link, a very easy way is as follows:

class FooModelAdmin(admin.ModelAdmin):
    list_display = ('foo_link', 'bar', 'another_bar', )
    list_display_links = ('foo_link', 'another_bar', )

If foo_link is not a property of the model, it should be a callable like the following:

class FooModelAdmin(admin.ModelAdmin):
    list_display = ('foo_link', 'bar', 'another_bar', )
    list_display_links = ('foo_link', 'another_bar', )

    def foo_link(self, obj):
        return "%s blah blah" % obj.some_property # or anything you prefer e.g. an edit button

A full example from my project:

class SchoolTeacherAdmin(admin.ModelAdmin):
    list_display = ('name', 'designation', 'school_name', 'school_code', 'date_of_birth', 'mobile', 'nid', 'edit', )
    list_display_links = ('edit', )

    def school_code(self, obj):
        return obj.school.code

    def school_name(self, obj):
        return obj.school.name.upper()

    def edit(self, obj):
        return "Edit"
👤Nayan

8👍

Here is the link to Django 3.1 documentation of the ModelAdmin option called ModelAdmin.list_display_links.

2👍

Needed something like this for a project. That was my solution to generate clickable references

from django.utils.safestring import mark_safe

@admin.register(models.Transaction)
class TransactionAdmin(admin.ModelAdmin):
    model = models.Transaction
    list_display = ('id', 'transaction_code', 'status', 'downloaded', 'realm',
                    'product_id', 'ticket', 'deleted', 'updated', 'created')
    search_fields = ("transaction_code", 'product_id', 'ticket_id')
    list_filter = ('status', 'downloaded', 'realm')
    readonly_fields = ('updated', 'created')
    change_form_template = 'admin/change_form_transaction.html'
    add_form_template = 'admin/change_form.html'
    list_display_links = ('id', )
    ordering = ('-created', )
    
    def ticket(self, obj):
        if obj.ticket_id:
            return mark_safe(f'<a href="https://ticketing.oursite.com/staff/index.php?/Tickets/Ticket/View/{obj.ticket_id}">{obj.ticket_id}</a>')
        return None
    
    ticket.allow_tags = True
    ticket.short_description = "ticket id"
👤Oleg

1👍

After following this idea myself (to link from the list display to the actual page) I had second thoughts. There are two pages that you have to consider: the admin page of the model and the actual public page (probably detail view) of the model. If you link from the admin to the public page (even if it is a CMS page) you loose the connection to its admin page.

The admin page of the model actually links to the public page via the “Preview” link (regularly placed at the top right). This link derives from model_object.get_absolute_url().

So, if you want to change where the preview link points you simply have to override get_absolute_url(). And in this case, it’s probably a good thing you do that, anyway, because you will likely want to make use of that url in all other places, as well.

0👍

You need to override the template since the link is wrapped there. Have a look at Edit Django User admin template.

Leave a comment