[Django]-Django: Any way to sort on model method in admin interface?

4👍

First of all you shouldn’t call len() on the queryset to get the number of items as it will not translate to sql’s COUNT but fetch all items of the database instead. Better use the queryset’s count() method:

latest_transactions = Transaction.objects.filter(book=self, transaction_type=0).count()

Sorting by a ForeignKey‘s count should be possible with something like that:

from django.db.models import Count
queryset = Book.objects.filter(transaction_type=0) \
                .annotate(num_transactions=Count('transaction')) \
                .order_by('-num_transactions')

For instructions on how to add a sortable column to django’s admin see this post!

1👍

The queryset used by an admin is exposed through the method queryset(). Neither my answer or lazerscience’s deals with your transaction type. So I went back to my example and said, “Those are only the awards those films tried to win. What if I only wanted those awards the films actually won?” That addresses your issue of counting only by those transactions of a certain type. Provided your SQL server supports the count() method internally (it had better!) the answer is:

class FilmAdmin(admin.ModelAdmin):
    def queryset(self, request):
        qs = super(FilmAdmin, self).queryset(request)
        qs = qs.extra(
            select = { 'award_count': 'select count(*) from films_filmaward where films_filmaward.film_id=films_film.id and films_filmaward.won=1' }
        )
        qs = qs.order_by('award_count')
        return qs

Additionally, if you want to display the award_count in your list, be aware that since it’s not a native field of the model it won’t be available when the admin builds its list builder factory. You can work around this by adding the following to your ModelAdmin class:

    def award_count(self, obj):
        return obj.award_count

    list_display = ('id', 'title', 'year', 'contact', 'award_count')

The list builder factory will see that there’s a method for generating the award count, and that method will have access to the rows generated by your queryset. Viola’, there you go.

Leave a comment