更改 django admin 中的列表显示链接

发布于 2024-09-28 18:56:46 字数 501 浏览 0 评论 0原文

我正在尝试更改 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>

I am trying to change the link for an object in the django admin list display. Here is what I have so far:

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"

This produces another link within the original list display link e.g.

<a href="/admin/app/model/pk/"><a href="/foos/foo/">Foo</a></a>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

时间海 2024-10-05 18:56:46

我相信正确的方法是子类化 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

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
只等公子 2024-10-05 18:56:46

解决方案是覆盖 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, )

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, )
白馒头 2024-10-05 18:56:46

默认情况下,列表显示的第一列将链接到管理编辑页面。如果您希望另一列或多列成为该链接,一个非常简单的方法如下:

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"

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"
池予 2024-10-05 18:56:46

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

永不分离 2024-10-05 18:56:46

一个项目需要这样的东西。这是我生成可点击参考的解决方案

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"

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"
一袭白衣梦中忆 2024-10-05 18:56:46

在我自己遵循这个想法(从列表显示链接到实际页面)之后,我有了新的想法。您必须考虑两个页面:模型的管理页面和模型的实际公共页面(可能是详细视图)。如果您从管理链接到公共页面(即使它是 CMS 页面),您就会失去与其管理页面的连接。

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

因此,如果您想更改预览链接指向的位置,您只需重写 get_absolute_url() 即可。在这种情况下,无论如何,您这样做可能是一件好事,因为您可能也想在所有其他地方使用该 url。

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.

小草泠泠 2024-10-05 18:56:46

您需要覆盖模板,因为链接被包装在那里。查看编辑 Django 用户管理模板

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文