Django Admin链接到相关对象

时间:2011-06-20 23:09:25

标签: django django-admin

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

class PageAdmin(admin.ModelAdmin):
    list_display = ('name', 'user', )
    list_display_links = ('name','user',)
admin.site.register(Page, PageAdmin)

我希望通过在list_display中创建一个链接,它默认链接到实际的用户对象,但它仍然转到Page。

我确信我在这里缺少一些简单的东西。

6 个答案:

答案 0 :(得分: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" 

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

  from django.template.defaultfilters import escape
  from django.core.urls import reverse

admin.py list_display中,添加user_link

list_display = ('name', 'user_link', )

无需list_display_links

答案 1 :(得分:4)

我决定制作一个看起来像这样的简单管理混合(请参阅docstring用法):

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

答案 2 :(得分:3)

您需要将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)))

答案 3 :(得分:3)

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

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))

答案 4 :(得分:2)

我在很多管理页面上都需要这个,所以我为它创建了一个处理不同用例的mixin。你只需添加:

change_links = ['field']

到你的ModelAdmin班。

有关详细信息,请参阅GitHub页面。尝试一下,让我知道它是如何工作的!

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

答案 5 :(得分:0)

如果有人尝试使用内联管理员执行此操作,请考虑自 Django 1.8 起名为 show_change_link 的属性。

您的代码可能如下所示:

class QuestionInline(admin.TabularInline):
    model = Question
    extra = 1
    show_change_link = True


class TestAdmin(admin.ModelAdmin):
    inlines = (QuestionInline,)


admin.site.register(Test, TestAdmin)

这将为管理员的内联部分中的每个外键关系添加一个更改/更新链接。