Django Admin链接到相关对象

Bre*_*den 27 django django-admin

我的应用有用户创建页面.在管理员的页面屏幕中,我想列出创建该页面的用户,并且在该列表中,我希望用户名具有一个链接到admin(而不是Page)中的用户页面.

class PageAdmin(admin.ModelAdmin):
    list_display = ('name', 'user', )
    list_display_links = ('name','user',)
admin.site.register(Page, PageAdmin)
Run Code Online (Sandbox Code Playgroud)

我希望通过使它成为list_display中的链接,它将默认链接到实际的用户对象,但它仍然转到Page.

我确定我在这里错过了一些简单的东西.

Why*_*ugo 39

修改你的模型是不必要的,这实际上是一个不好的做法(在你的模型中添加特定于管理员的视图逻辑?哎呀!)在某些情况下甚至可能不可能.

幸运的是,它可以从ModelAdmin类中实现:

from django.urls import reverse
from django.utils.safestring import mark_safe    


class PageAdmin(admin.ModelAdmin):
    # Add it to the list view:
    list_display = ('name', 'user_link', )
    # Add it to the details view:
    read_only_fields = ('user_link',)

    def user_link(self, obj):
        return mark_safe('<a href="{}">{}</a>'.format(
            reverse("admin:auth_user_change", args=(obj.user.pk,)),
            obj.user.email
        ))
    user_link.short_description = 'user'


admin.site.register(Page, PageAdmin)
Run Code Online (Sandbox Code Playgroud)

编辑2016-01-17:
更新了使用的答案make_safe,因为allow_tags现在已弃用.

  • `readonly_fields =('user_link')`not`read_only_fields =('user_link')` (5认同)
  • 更好的`obj.user.pk`,以防主键未被称为`id`. (4认同)
  • 可能想使用 `format_html('&lt;a...{}..., mark_safe(reverse(...)), obj.user.email)` 来转义 `&lt;a&gt;` 的正文,以防万一不要相信它 https://docs.djangoproject.com/en/2.0/ref/utils/#django.utils.html.format_html (4认同)
  • 谢谢,比另一个更好的答案!(可能可以理解,因为 Django 自 2011 年以来已经发展了很多......) (2认同)
  • 这可以概括为允许 list_display 中的任何相关模型进行超链接吗? (2认同)

Udi*_*Udi 16

将此添加到您的模型:

  def user_link(self):
      return '<a href="%s">%s</a>' % (reverse("admin:auth_user_change", args=(self.user.id,)) , escape(self.user))

  user_link.allow_tags = True
  user_link.short_description = "User" 
Run Code Online (Sandbox Code Playgroud)

您可能还需要将以下内容添加到顶部models.py:

  from django.template.defaultfilters import escape
  from django.core.urls import reverse
Run Code Online (Sandbox Code Playgroud)

admin.py,在list_display,添加user_link:

list_display = ('name', 'user_link', )
Run Code Online (Sandbox Code Playgroud)

没必要list_display_links.

  • 请...没有人这样做。WhyNotHugo 的答案更加清晰。 (3认同)
  • 谢谢!澄清一下,将其添加到我的页面模型中? (2认同)
  • 那是另一个模型“auth_user”+下划线+“change”——所以如果另一个模型是frobnicate——那就是frobnicate_change。 (2认同)

Jan*_*zny 10

您需要将format_html用于现代版本 od django

@admin.register(models.Foo)
class FooAdmin(admin.ModelAdmin):
    list_display = ('ts', 'bar_link',)

    def bar_link(self, item):
        from django.shortcuts import resolve_url
        from django.contrib.admin.templatetags.admin_urls import admin_urlname
        url = resolve_url(admin_urlname(models.Bar._meta, 'change'), item.bar.id)
        return format_html('<a href="{url}">{name}</a>'.format(url=url, name=str(item.bar)))
Run Code Online (Sandbox Code Playgroud)

  • 不要忘记添加“ from django.utils.html import format_html ” (2认同)

imb*_*olc 7

我最终得到了一个简单的帮手:

from django.shortcuts import resolve_url
from django.utils.safestring import SafeText
from django.contrib.admin.templatetags.admin_urls import admin_urlname
from django.utils.html import format_html


def model_admin_url(obj: Model, name: str = None) -> str:
    url = resolve_url(admin_urlname(obj._meta, SafeText("change")), obj.pk)
    return format_html('<a href="{}">{}</a>', url, name or str(obj))
Run Code Online (Sandbox Code Playgroud)

然后你可以在你的模型管理员中使用帮助器:

class MyAdmin(admin.ModelAdmin):
    readonly_field = ["my_link"]

    def my_link(self, obj):
        return model_admin_url(obj.my_foreign_key)
Run Code Online (Sandbox Code Playgroud)

  • 你能添加如何使用它吗? (2认同)
  • @HarryMoreno 当然,补充道 (2认同)

git*_*rik 6

我的很多管理页面都需要这个,所以我为它创建了一个 mixin 来处理不同的用例:

pip install django-admin-relation-links
Run Code Online (Sandbox Code Playgroud)

然后:

from django.contrib import admin
from django_admin_relation_links import AdminChangeLinksMixin


@admin.register(Group)
class MyModelAdmin(AdminChangeLinksMixin, admin.ModelAdmin):

    # ...

    change_links = ['field_name']
Run Code Online (Sandbox Code Playgroud)

请参阅 GitHub 页面了解更多信息。尝试一下,让我知道效果如何!

https://github.com/gitaarik/django-admin-relation-links


Mik*_*koP 5

我决定制作一个简单的管理 mixin,如下所示(有关用法,请参阅文档字符串):

from django.contrib.contenttypes.models import ContentType
from django.utils.html import format_html
from rest_framework.reverse import reverse


class RelatedObjectLinkMixin(object):
    """    
    Generate links to related links. Add this mixin to a Django admin model. Add a 'link_fields' attribute to the admin
    containing a list of related model fields and then add the attribute name with a '_link' suffix to the
    list_display attribute. For Example a Student model with a 'teacher' attribute would have an Admin class like this:

    class StudentAdmin(RelatedObjectLinkMixin, ...):
        link_fields = ['teacher']

        list_display = [
            ...
            'teacher_link'
            ...
        ]
    """

    link_fields = []

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.link_fields:
            for field_name in self.link_fields:
                func_name = field_name + '_link'
                setattr(self, func_name, self._generate_link_func(field_name))

    def _generate_link_func(self, field_name):
        def _func(obj, *args, **kwargs):
            related_obj = getattr(obj, field_name)
            if related_obj:
                content_type = ContentType.objects.get_for_model(related_obj.__class__)
                url_name = 'admin:%s_%s_change' % (content_type.app_label, content_type.model)
                url = reverse(url_name, args=[related_obj.pk])
                return format_html('<a href="{}" class="changelink">{}</a>', url, str(related_obj))
            else:
                return None
        return _func
Run Code Online (Sandbox Code Playgroud)