django管理列表中的外键显示

Oli*_*ier 37 django foreign-keys django-admin

如果django模型包含外键字段,并且该字段以列表模式显示,则它显示为文本,而不是显示指向外部对象的链接.

是否可以自动将所有外键显示为链接而不是平面文本?

(当然可以逐场进行,但有一般方法吗?)

示例:

class Author(models.Model):
    ...

class Post(models.Model):
    author = models.ForeignKey(Author)
Run Code Online (Sandbox Code Playgroud)

现在我选择一个ModelAdmin,以便作者以列表模式显示:

class PostAdmin(admin.ModelAdmin):
    list_display = [..., 'author',...]
Run Code Online (Sandbox Code Playgroud)

现在在列表模式下,作者字段将只使用类的__unicode__方法Author来显示作者.最重要的是,我希望链接指向管理站点中相应作者的URL.那可能吗?

手动方式:

为了完整起见,我添加了手动方法.这将是author_linkPostAdmin类中添加一个方法:

def author_link(self, item):
    return '<a href="../some/path/%d">%s</a>' % (item.id, unicode(item))
author_link.allow_tags = True
Run Code Online (Sandbox Code Playgroud)

这将适用于该特定领域,但这不是我想要的.我想要一种通用的方法来达到同样的效果.(其中一个问题是如何自动计算django管理站点中对象的路径.)

小智 18

我一直在寻找解决同样问题的方法并遇到了这个问题......最后我自己解决了这个问题.OP可能不再感兴趣,但这对某人仍然有用.

from functools import partial
from django.forms import MediaDefiningClass

class ModelAdminWithForeignKeyLinksMetaclass(MediaDefiningClass):

    def __getattr__(cls, name):

        def foreign_key_link(instance, field):
            target = getattr(instance, field)
            return u'<a href="../../%s/%s/%d">%s</a>' % (
                target._meta.app_label, target._meta.module_name, target.id, unicode(target))

        if name[:8] == 'link_to_':
            method = partial(foreign_key_link, field=name[8:])
            method.__name__ = name[8:]
            method.allow_tags = True
            setattr(cls, name, method)
            return getattr(cls, name)
        raise AttributeError

class Book(models.Model):
    title = models.CharField()
    author = models.ForeignKey(Author)

class BookAdmin(admin.ModelAdmin):
    __metaclass__ = ModelAdminWithForeignKeyLinksMetaclass

    list_display = ('title', 'link_to_author')
Run Code Online (Sandbox Code Playgroud)

如果不使用python> = 2.5,用Django的'curry'替换'partial'.


cet*_*eek 9

我不认为有一种机制可以自动开箱即用.

但是,只要根据对象的id确定管理编辑页面的路径,您只需要两条信息:

一个) self.model._meta.app_label

b) self.model._meta.module_name

然后,例如,要转到该模型的编辑页面,您将执行以下操作:

'../%s_%s_change/%d' % (self.model._meta.app_label, self.model._meta.module_name, item.id)
Run Code Online (Sandbox Code Playgroud)

看看django.contrib.admin.options.ModelAdmin.get_urls他们是如何做到的.

我想你可以有一个带有模型名称和id的callable,创建一个指定类型的模型,只是为了得到标签和名称(不需要点击数据库)并生成上面的URL.

但是你确定你无法使用内联吗?它将使更好的用户界面在一个页面中包含所有相关组件......

编辑:

联(链接到文档)允许管理界面在一个页面中显示父子关系,而不是将其分成两个.

在您提供的帖子/作者示例中,使用内联将意味着用于编辑帖子的页面还将显示用于添加/编辑/删除作者的内联表单.对最终用户来说更自然.

您可以在管理列表视图中执行的操作是在Post模型中创建一个可调用对象,该模型将呈现以逗号分隔的作者列表.因此,您将在帖子列表视图中显示正确的作者,并直接在Post管理界面中编辑与帖子关联的作者.


ado*_*rev 5

请参阅https://docs.djangoproject.com/en/stable/ref/contrib/admin/#admin-reverse-urls

例子:

from django.utils.html import format_html
def get_admin_change_link(app_label, model_name, obj_id, name):
    url = reverse('admin:%s_%s_change' % (app_label, model_name),
              args=(obj_id,))
    return format_html('<a href="%s">%s</a>' % (
        url, unicode(name)
    ))
Run Code Online (Sandbox Code Playgroud)