Search code examples
djangodjango-admin

Django Admin: list_display() order by count of related object


Imagine you have a model Person which can have N Book instances.

I want to display the number of books a person has in the django admin change-list view.

It is easy to display the number (write a custom method on PersonAdmin).

But I could not find a way to make it sortable by the number of books a person has.

I read the docs for list_display, but could not find an answer.

According to the docs a query expression could be used. Is it possible to solve it this way?

After applying the answer, this is what it looks like. In this case each instance has N log entries:

order-by-log-count


Solution

  • Override the get_queryset() method of model admin with the help of annoate() and order_by() methods. Then, define a callable function(book_count()) to return the value to the change-list page

    from django.db.models.aggregates import Count
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = ('book_count', 'other_field')
    
        def get_queryset(self, request):
            qs = super().get_queryset(request)
            qs = qs.annotate(book_count=Count('book')).order_by('-book_count')
            return qs
    
        def book_count(self, person_instance):
            return person_instance.book_count
    
        book_count.admin_order_field = 'book_count'
    

    Why I didn't add ordering ?

    While we calling the super(), Django will throw exceptions