如何向具有多对一关系的模型的 Django 管理添加可排序计数列?

问题描述 投票:0回答:5

假设我有一个 Book 模型,其中包含 Publisher 模型的外键。

如何在 Django 管理中显示每个出版商出版的书籍数量的列,以便我可以使用内置排序?

django django-models django-admin
5个回答
88
投票

我遇到了同样的问题(我无法更改模型的管理器来添加缓慢的注释或连接)。这里的两个答案的组合是有效的。 @Andre 非常接近,Django 管理员支持仅修改管理员的查询集,因此在此处应用相同的逻辑,然后使用 admin_order_field 属性。当然,您仍然需要将新的管理字段添加到 list_display 中。

姜戈< 1.6:

from django.db.models import Count

class EventAdmin(admin.ModelAdmin)
    list_display = (..., 'show_artist_count')

    def queryset(self, request):
        qs = super(EventAdmin, self).queryset(request)
        return qs.annotate(artist_count=Count('artists'))

    def show_artist_count(self, inst):
        return inst.artist_count
    show_artist_count.admin_order_field = 'artist_count'

Django > 1.6:

from django.db.models import Count

class EventAdmin(admin.ModelAdmin)
    list_display = (..., "show_artist_count")

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.annotate(artist_count=Count("artists"))

    def show_artist_count(self, inst):
        return inst.artist_count
    show_artist_count.admin_order_field = "artist_count"

8
投票

试试这个:

创建一个新的 Manager (和 aggregate,并在图书关系字段上进行计数):

class PublisherManager(models.Manager):
    def get_query_set(self):
        return super(PublisherManager,self).get_query_set().annotate(pubcount=Count('book'))

pubcount
排序:

class Publisher(models.Model):
    ......
    objects = PublisherManager()

    class Meta:
        ordering = ('pubcount',)

1
投票

您确实应该从添加开始:

class PublisherManager(models.Manager):
    def get_query_set(self):
        return super(PublisherManager,self).get_query_set().annotate(pubcount=Count('book'))

但是将其添加为可排序字段的正确方法是:

class Publisher(models.Model):
    ......
    objects = PublisherManager()

    def count(self):
        return self.pubcount
    count.admin_order_field = 'pubcount'

然后您可以将“count”添加到 admin.py 中模型管理的 list_display 属性中


0
投票

Lincoln B 的答案对我来说是正确的方法。

起初我只想评论他的解决方案,但实际上我发现自己解决了一个稍微不同的问题。我有一个管理类,我想根据我的需要“定制”它 - 即

django-taggit
管理员。在我的一份申请中,我添加了:

admin.py

对我来说有趣的观察是,我不能只注释 
# sort tags by name in admin (count items also possible) from taggit.admin import TagAdmin TagAdmin.ordering = ["name"] # make sortable on item_count: # 1. function for lookup def item_count(obj): """This takes the item_count from object: didn't work as model field.""" return obj.item_count # not needed: obj.taggit_taggeditem_items.count() # 2. property in function - admin field name item_count.admin_order_field = 'item_count' # 3. queryset override, with count annotation from django.db.models import Count TagAdmin.queryset = lambda self, request: super(TagAdmin, self).queryset(request).annotate(item_count=Count('taggit_taggeditem_items')) # 4. add to list display TagAdmin.list_display = ["name", item_count]

,并将

queryset
添加到
"item_count"
- 因为
list_display
中没有
item_count
方法,
TagAdmin
中也没有方法或字段Tag
模型类(仅在
queryset
中)。


-2
投票
尝试这样的事情:

class PublisherAdminWithCount(Admin): def book_count(self, obj): return obj.book_set.count() list_display = ('user_count',) admin.site.register(Group, PublisherAdminWithCount)
    
© www.soinside.com 2019 - 2024. All rights reserved.