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

时间:2010-08-16 08:57:17

标签: django django-models django-admin

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

我如何在Django管理员中显示每个发布者发布的图书数量的列,我可以使用内置排序?

5 个答案:

答案 0 :(得分:75)

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

from django.db.models import Count

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

    def queryset(self, request):
    # def get_queryset(self, request):    for Django 1.6+
        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'

答案 1 :(得分: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',)

答案 2 :(得分: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'

然后你可以在admin.py

中将'count'添加到model admin的list_display属性中

答案 3 :(得分:0)

尝试这样的事情:

class PublisherAdminWithCount(Admin):

    def book_count(self, obj):
        return obj.book_set.count()

    list_display = ('user_count',)

admin.site.register(Group, PublisherAdminWithCount)

答案 4 :(得分:0)

林肯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方法1}},也不是Tag模型类中的方法或字段(仅限于queryset)。