Django Admin list_display 添加列[统计相关ForeignKey的记录]

Posted

技术标签:

【中文标题】Django Admin list_display 添加列[统计相关ForeignKey的记录]【英文标题】:Django Admin list_display add column [count records of related ForeignKey] 【发布时间】:2017-04-09 09:25:34 【问题描述】:

我是 Python 和 Django 的新手。

我试图计算模型的外键项/记录,并将其显示为 Admin list_display 中的一列。

所以我有一个模型“作者”,作为模型“书”的外键。

这是models.py:

class Author(models.Model):

    name = models.CharField(
        max_length=100,
    )

    class Meta:
        ordering = ['-name ']
        verbose_name = _('Author')
        verbose_name_plural = _('Authors')

    def __str__(self):
        return self.author

    @models.permalink
    def get_absolute_url(self):
        return reverse('author_detail', kwargs='pk': self.pk)

class Book(models.Model):
    author = models.ForeignKey(
        'Author',
        related_name='menu_items', 
        verbose_name=_('author'),
    )

    bookname= models.CharField(
        max_length=100,
    )

    publisher= models.CharField(
        max_length=100,
    )
    class Meta:
        ordering = ['-bookname']
        verbose_name = _('Book')
        verbose_name_plural = _('Books')

    def __str__(self):
        return self.bookname

    @models.permalink
    def get_absolute_url(self):
        return ('book_detail', [self.pk])

这是 admin.py

from django.contrib import admin
from .models import Author, Book

class BookInline(admin.TabularInline):
    model = Book
    extra = 1

@admin.register(Author)
class LibraryAdmin(admin.ModelAdmin):
    def NumberOfBooks(self, obj):
        #I guess sth is wrong here when trying to count the book_set
        return obj.book_set.count()

    NumberOfBooks.short_description = "Books Count"
    list_display = ['bookname', 'publisher', 'NumberOfBooks']
    inlines = [BookInline]

我想统计每个作者写了多少本书,并在管理页面的第二级显示如下Home>Authors>Author

 Author | Books Count
Someone1  NumberOfBooks
Someone2  NumberOfBooks
Someone3  NumberOfBooks
Someone4  NumberOfBooks

但是我得到了错误:

'Author' object has no attribute 'book_set'

1.我做错了 obj.book_set.count() 吗? 我以为obj.book_set 会引用同一个“作者”(obj)下的“书”,听起来我误解了它,但我不确定如何实现我的意图。

2。相反,如果我想在“作者”中添加一个字段,该字段将自动计算与每个作者相关的“书”的数量,这应该是一种更好的方法吗?该怎么做?

【问题讨论】:

【参考方案1】:

错误页面上应该有一个包含所有可用字段的列表,并且您应该找到一个名为 menu_items 的字段(这就是您在 Book 模型中放入 related_name 的内容)。

但这可能不是最好的选择。您应该能够像这样覆盖 LibraryAdmin(admin.ModelAdmin) 类上的 get_queryset() 方法:

...
from django.db.models import Count
...

@admin.register(Loan)
class LibraryAdmin(admin.ModelAdmin):

    def get_queryset(self, request):
        qs = super(LibraryAdmin, self).get_queryset(request)
        return qs.annotate(books_count=Count('menu_items'))

    def books_count(self, inst):
        return inst.books_count

    list_display = ['bookname', 'publisher', 'books_count']
    inlines = [BookInline]

这样计数将由您的数据库完成。

【讨论】:

` ERRORS: : (admin.E108) 'list_display[3]' 的值是指'books_count',它不是可调用的,是属性'LibraryAdmin',或'authors.Author' 的属性或方法。` 这是我遇到的错误,我现在真的很困惑......顺便说一下@admin.register(Loan) 应该是@admin.register(Author),我打错了,但这不是问题所在,例如,我改变了名称稍微便于理解。 我终于通过添加:def show_books_count(self, inst): return inst.books_count list_display = ['bookname', 'publisher', 'show_books_count'] 得到了这项工作,但你能解释一下为什么这样做以及(self, inst) 是做什么的吗?可以简化并添加到def get_queryset吗? 你得到了那个错误,因为 books_count 模型类中缺少 Admin 属性,确实,我错过了像你这样的方法。 inst 是一个具体的对象,它有一个 books_count 属性,因为我们 annotate()d 查询集。 @GregKaleka 在Book 模型上有一个related_name='menu_items'。这就是为什么这里应该是qs.annotate(books_count=Count('menu_items'))

以上是关于Django Admin list_display 添加列[统计相关ForeignKey的记录]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django admin 中本地化 list_display 字段?

Django admin list_display 在鼠标悬停时显示全文

如何忽略在 django admin list_display 中加载巨大的字段?

Django admin:从反向 FK 聚合中排序 list_display 字段

Django Admin list_display 添加列[统计相关ForeignKey的记录]

从 django admin list_display 访问,来自一对一表的值