【问题标题】:How can I list all foreign key related objects in Django admin panel?如何在 Django 管理面板中列出所有与外键相关的对象?
【发布时间】:2013-09-30 14:06:35
【问题描述】:

我想用 django 管理面板实现一个非常简单的功能,但到目前为止我找不到实现此功能的正确方法:

模型.py

class Author(models.Model):
    name = models.CharField()

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

admin.py

class AuthorAdmin(admin.ModelAdmin):
    pass
admin.site.register(Author, AuthorAdmin)

如何为作者列表概览中的每个项目(作者)添加超链接,以链接到显示特定作者所有书籍的视图?例如:

  • J.K.罗琳(书籍)
  • J.R.R.托尔金(书籍)

books 是指向显示作者所有书籍的网站的超链接。

【问题讨论】:

    标签: python django django-admin


    【解决方案1】:

    您正在寻找ModelAdmin.list_filter

    设置 list_filter 以激活管理员更改列表页面右侧栏中的过滤器。 listfilter 可以是字段名,其中指定的字段应该是 BooleanField、CharField、DateField、DateTimeField、IntegerField、ForeignKey 或 ManyToManyField,例如:

     # Add a list filter author to BookAdmin.
     # Now you can filter books by author.
     class BookAdmin(ModelAdmin):
        list_filter = ('author', )
    

    现在您可以使用@Wolph 建议在作者列表显示中添加一个链接。此链接指向按作者过滤的书单:

    # Add hyperlinks to AuthorAdmin.
    # Now you can jump to the book list filtered by autor. 
    class AuthorAdmin(admin.ModelAdmin):
        def authors(self):
            return '<a href="/admin/appname/book/?author__id__exact=%d">%s</a>' % (self.author_id, self.author)
        authors.allow_tags = True
    

    替代方案。要保存点击,您还可以直接指向图书的更改视图:

    class Books(models.Model):
        title = models.CharField()
        author = models.ForeignKey(Author)
    
    def get_admin_url(self):
        return "/admin/appname/books/%d/" %self.id
    
    
    class BookAdmin(admin.ModelAdmin):
        def authors(self):
            html = ""
            for obj in Books.objects.filter(author__id_exact=self.id):
                html += '<p><a href="%s">%s</a></p>' %(obj.get_admin_url(), obj.title)
            return html
        authors.allow_tags = True
    
        list_display = ['title', authors]
    

    免责声明:未经测试,但如果您修正错字,它会起作用! :)

    请注意,这些链接也可以在管理员的其他位置注入。当您将其添加到小部件时,您可以从更改视图转到更改视图。

    【讨论】:

    • 感谢您的回答。我必须在“书籍”方面进行哪些更改才能使其正常工作?目前结果仍然包括数据库中的所有书籍(当然)。
    • 我的错。列表过滤器位于 BookAdmin。查看更新。
    • with authors.allow_tags = True 它终于可以工作了 :) 关于这个问题的最后一个问题:你能告诉我如何用 urlresolver 替换 '/admin/appname/book/' 吗?
    • 不,在这种情况下我从未使用过 url 解析器。因为我只在管理员中使用它,它的结构基于模型,因此变化不大。但是如果你想让它更加动态,你可以研究一个模型属性来创建作者链接docs.djangoproject.com/en/1.5/topics/db/models/#model-methods 并看看 Django 如何构造related_name 属性。 docs.djangoproject.com/en/1.5/topics/db/models/…“%(app_label)s_%(class)s_related”。但也许有更好的方法。
    【解决方案2】:

    研究实现InlineModelAdmin 对象。

    # admin.py
    class BooksInline(admin.TabularInline):
        model = Books
    
    class AuthorAdmin(admin.ModelAdmin):
        inlines = [BooksInline]
    

    根据 OP 的评论编辑答案:

    class AuthorAdmin(admin.ModelAdmin):
        list_display = ['name', 'books_published']
    
        def books_published(self, obj):
            redirect_url = reverse('admin:books_changelist')
            extra = "?author__id__exact=%d" % (obj.id)
            return "<a href='%s'>Books by author</a>" % (redirect_url + extra)
    
        books_published.allow_tags = True
    

    【讨论】:

    • 当我正确理解 InlineModelAdmin 时,它是用于在作者表单中编辑和添加书籍的目的。我正在寻找仅书籍的列表概述
    • 感谢您的编辑。我必须在“书籍”方面进行哪些更改才能使其正常工作?目前结果仍然包括数据库中的所有书籍(当然)。
    • 代码中的“额外”变量应该过滤单个作者在更改列表页面上返回的查询集。你所有的书都是同一个作者的吗?如果我在某处有错字,您可能需要稍微调整字符串值。
    【解决方案3】:

    这并不像您想象的那么简单,可能但并非微不足道,因为没有太多关于此功能的文档:)

    您需要的是一个自定义列,该列由一个函数生成,该函数为您提供带有给定过滤器的 Django 管理员链接。像这样的东西(从我的头顶,所以没有测试)应该可以解决问题:

    class AuthorAdmin(admin.ModelAdmin):
        def authors(self):
            return '<a href="?author=%d">%s</a>' % (self.author_id, self.author)
        authors.allow_html = True
    
        list_display = ['title', authors]
    

    【讨论】:

      猜你喜欢
      • 2021-09-12
      • 2021-08-25
      • 2022-11-27
      • 1970-01-01
      • 2012-12-24
      • 2021-06-26
      • 1970-01-01
      • 2018-02-12
      • 2015-04-16
      相关资源
      最近更新 更多