【问题标题】:Foreign keys in django admin list displaydjango 管理列表中的外键显示
【发布时间】:2011-01-29 01:01:01
【问题描述】:

如果 django 模型包含外键字段,并且该字段以列表模式显示,则它显示为 文本,而不是显示 链接异物。

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

(当然可以逐个字段进行,但有通用的方法吗?)

示例

class Author(models.Model):
    ...

class Post(models.Model):
    author = models.ForeignKey(Author)

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

class PostAdmin(admin.ModelAdmin):
    list_display = [..., 'author',...]

现在在列表模式下,作者字段将只使用Author 类的__unicode__ 方法来显示作者。最重要的是,我想要一个 link 指向管理站点中相应作者的 url。这可能吗?

手动方法

为了完整起见,我添加了手动方法。就是在PostAdmin类中添加一个方法author_link

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

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

【问题讨论】:

    标签: django django-admin foreign-keys


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      我认为没有一种机制可以开箱即用地自动执行您想要的操作。

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

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

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

      我想你可以有一个可调用的,它接受模型名称和 id,创建指定类型的模型只是为了获取标签和名称(无需访问数据库)并生成上面的 URL。

      但是你确定你不能使用内联吗?将所有相关组件都放在一个页面中,这将有助于提供更好的用户界面...

      编辑:

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

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

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

      【讨论】:

      • 感谢您的回答!你能详细说明内联的使用吗?这有什么帮助?
      • @Olivier:编辑了我的答案,为你指出关于内联的正确方向。
      【解决方案3】:

      我一直在寻找解决同一问题的方法,但遇到了这个问题……最终我自己解决了。 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')
      

      如果不使用 python >= 2.5,请将 'partial' 替换为 Django 的 'curry'。

      【讨论】:

      • Itai Tavor,谢谢你的回答,真的是很糟糕,但可能会导致问题,详情在my answer to another question
      • 对我来说,使用 %s 的绝对路径效果更好,因为当链接正确时在对象详细信息页面上,而不仅仅是在列表页面上。
      • ModelAdminWith... 方法的参数是什么?我没有“MediaDefineClass”作为表单?
      • 漂亮的解决方案。必须将“target._meta.module_name”更改为“target._meta.model_name”。效果很好。
      猜你喜欢
      • 1970-01-01
      • 2014-10-14
      • 2012-07-05
      • 1970-01-01
      • 2012-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多