Как добавить отсортированный столбец графа в администратор Django модели с отношением "много-к-одному"?
Предположим, что у меня есть модель книги, содержащая внешний ключ для модели Publisher.
Как я могу отобразить в администраторе Django столбец с количеством книг, опубликованных каждым издателем, таким образом, чтобы я мог использовать встроенную сортировку?
Ответы
Ответ 1
У меня была такая же проблема (я не могу изменить диспетчер модели, чтобы добавлять медленные аннотации или объединения). Здесь работает комбинация двух ответов. @Andre действительно близок, Django Admin поддерживает модификацию набора запросов только для администратора, поэтому примените ту же логику здесь, а затем добавьте атрибут admin_order_field. Вам все равно нужно добавить новое поле admin в список_дисплей, конечно.
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'
Ответ 2
Попробуйте следующее:
создайте новый 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',)
Ответ 3
Вы должны начать с добавления:
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
Ответ 4
Попробуйте что-то вроде этого:
class PublisherAdminWithCount(Admin):
def book_count(self, obj):
return obj.book_set.count()
list_display = ('user_count',)
admin.site.register(Group, PublisherAdminWithCount)
Ответ 5
Ответ 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
- потому что в TagAdmin
не было метода item_count
, а не метода или поля в класс модели Tag
(только в queryset
).