Как добавить столбец сортируемого количества к администратору Django модели с отношением «многие к одному»? - PullRequest
47 голосов
/ 16 августа 2010

Предположим, у меня есть модель Book, содержащая внешний ключ к модели Publisher.

Как отобразить в администраторе Django столбец с количеством книг, опубликованных каждым издателем, таким образом, чтобы я могиспользовать встроенную сортировку?

Ответы [ 5 ]

76 голосов
/ 28 декабря 2010

У меня была такая же проблема (я не могу изменить менеджера моей модели, чтобы добавить медленные аннотации или объединения). Сочетание двух ответов здесь работает. @Andre действительно близко, администратор Django поддерживает изменение набора запросов только для администратора, поэтому примените ту же логику здесь, а затем используйте атрибут 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'
8 голосов
/ 16 августа 2010

Попробуйте это:

создать нового менеджера агрегат с подсчетом в поле отношения книги):

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 голос
/ 16 августа 2010

Вы действительно должны начать с добавления:

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' к атрибуту list_display администратора модели в admin.py

0 голосов
/ 28 мая 2013

Ответ Линкольна Б. был для меня верным.

Сначала я хотел просто прокомментировать его решение, но на самом деле я решил, что решаю немного другую проблему. У меня был класс администратора, который я хотел «настроить» под свои нужды, а именно - django-taggit admin. В одном из моих приложений 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 - потому что в TagAdmin не было ни метода item_count, ни метода или поля Tag модель класса (только в queryset).

0 голосов
/ 16 августа 2010

Попробуйте что-то вроде этого:

class PublisherAdminWithCount(Admin):

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

    list_display = ('user_count',)

admin.site.register(Group, PublisherAdminWithCount)
...