代码之家  ›  专栏  ›  技术社区  ›  Olivier Verdier

Django管理列表显示中的外键

  •  37
  • Olivier Verdier  · 技术社区  · 14 年前

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

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

    (当然可以逐场进行,但是否有通用方法?)

    例子 :

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

    现在我选择一个modeladmin,这样作者将以列表模式显示:

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

    现在在列表模式下,author字段将只使用 __unicode__ 方法 Author 类以显示作者。除此之外,我想要一个 链接 指向管理网站中相应作者的URL。有可能吗?

    手工法 :

    为了完整起见,我添加了手动方法。它将添加一个方法 author_link PostAdmin 班级:

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

    这对那个特定的领域是有用的,但是 我想要什么。我想要一个通用的方法来达到同样的效果。(问题之一是如何自动确定Django管理站点中对象的路径。)

    3 回复  |  直到 7 年前
        1
  •  9
  •   fredley    10 年前

    我认为没有一种机制可以自动完成你想要的事情。

    但是,就根据对象的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 A。

    但是你确定你不能通过使用inlines得到吗?将所有相关的组件放在一个页面中,这将有助于更好的用户界面…

    编辑:

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

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

    您可以在管理列表视图中执行的操作是在发布模型中创建一个可调用的,该模型将呈现一个逗号分隔的作者列表。因此,您将让您的文章列表视图显示适当的作者,并在文章管理界面中直接编辑与文章关联的作者。

        2
  •  18
  •   Itai Tavor    14 年前

    我正在寻找解决这个问题的方法,并遇到了这个问题…最后我自己解决了。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,则将“部分”替换为django的“curry”。

        3
  •  3
  •   arheops    7 年前

    参见 https://docs.djangoproject.com/en/1.10/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)
        ))