How to add a sorted column column to a Django admin model with a many-to-one relationship?

Suppose I have a book model that contains a foreign key for a Publisher model.

How can I display in Django admin a column with the number of books published by each publisher so that I can use the built-in sort?

+41
django django-models django-admin
Aug 16 '10 at 8:57
source share
5 answers

I had the same problem (I cannot change the model manager to add slow annotations or joins). A combination of two answers works here. @Andre is really close, Django Admin supports modifying the set of requests only for the administrator, so apply the same logic here and then add the admin_order_field attribute. You still need to add a new admin field to the display_list, of course.

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' 
+66
Dec 28 '10 at 16:13
source share

Try the following:

create a new Manager (and aggregate considering the relation field to the book):

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

sort by pubcount :

 class Publisher(models.Model): ...... objects = PublisherManager() class Meta: ordering = ('pubcount',) 
+7
Aug 16 '10 at 9:30
source share

You should start by adding:

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

But the correct way to add it as a sortable field:

 class Publisher(models.Model): ...... objects = PublisherManager() def count(self): return self.pubcount count.admin_order_field = 'pubcount' 

And then you can just add 'count' to the list.display attribute of the admin.py model admin

+1
Aug 16 '10 at 18:22
source share

Try something like this:

 class PublisherAdminWithCount(Admin): def book_count(self, obj): return obj.book_set.count() list_display = ('user_count',) admin.site.register(Group, PublisherAdminWithCount) 
0
Aug 16 '10 at 9:07
source share

Lincoln B's answer was right for me.

At first, I just wanted to comment on his solution, but in fact I decided to solve a slightly different problem. I had an admin class that I wanted to β€œconfigure” for my needs, namely the django-taggit . In one of my admin.py applications admin.py I added:

 # 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] 

What was interesting to me was that I could not just comment on queryset and add "item_count" to list_display - because TagAdmin did not have an item_count method, and not a method or field in the Tag model class (only in queryset ).

0
May 28 '13 at 9:59
source share



All Articles