在Django管理后台中更改列表显示的链接

33

我正在尝试更改Django管理列表中对象的链接。这是目前我的代码:

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)
    domain_link.allow_tags = True
    domain_link.short_description = "foo"

这将在原始列表显示链接中生成另一个链接,例如:

<a href="/admin/app/model/pk/"><a href="/foos/foo/">Foo</a></a>
7个回答

38

我相信正确的做法是,继承ChangeList并重写url_for_result方法来创建你想要的正确更改url。

在admin.ModelAdmin子类中覆盖get_changelist以返回新类:

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

37
解决方法是覆盖init并将list_display_links设置为None,例如:
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, )

2
使用Django 3.0时,allow_tags对我无效,但在返回之前在HTML上应用mark_safe - Gnietschow

18

默认情况下,列表显示的第一列将链接到管理编辑页面。如果您想要其他列成为该链接,有一个非常简单的方法:

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

如果 foo_link 不是该模型的属性,它应该是以下形式的可调用对象:

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

我的项目中的完整示例:

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"

8

2
它在3.1之前就可用了,我使用的是2.2,那里面有。https://docs.djangoproject.com/en/2.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display_links - Harry Moreno
这个答案只适用于当你想要链接是“编辑”功能的情况;对于通用链接,这并不适用,而且问题本身也没有明确指定。 - undefined

2

我在项目中需要类似的东西。这是我生成可点击引用的解决方案

@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"

1
mark_safe确实是解决原始问题的方法。 - undefined

1

在我自己尝试了这个想法之后(从列表显示链接到实际页面),我开始犹豫了。你需要考虑两个页面:模型的管理页面和模型的实际公共页面(可能是详细视图)。如果你从管理页面链接到公共页面(即使是CMS页面),你将失去与其管理页面的连接。

模型的管理页面实际上通过“预览”链接(通常位于右上角)链接到公共页面。此链接源自 model_object.get_absolute_url()

所以,如果你想改变预览链接指向何处,你只需覆盖 get_absolute_url()。在这种情况下,这样做可能是一个好主意,因为你很可能希望在所有其他地方使用该url。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接