djangopython-3.xdjango-admindjango-admin-filters

How can I display the number of items per category in the Django admin filter panel?


In Django admin, how could I add the number of items for each category of a filter directly in the filter panel (see mock-up below)?

Current filter panel

Current filter

Desired filter panel

Desired filter

Model

I am filtering my UserProfile table by its languages field. This is a many-to-many field on the Language table.

class UserProfile(models.Model):
    # ...
    languages = models.ManyToManyField(Language, blank=True)

class Language(models.Model):
    name = models.CharField(max_length=64)
    # ...

My current admin configuration is:

@admin.register(UserProfile):
class UserProfileAdmin(admin.ModelAdmin):
    # ...
    list_filter = ('languages',)

Solution

  • This should work:

    class UserProfileLanguageFilter(admin.SimpleListFilter):
        title = _('Language')
        parameter_name = 'languages'
    
        def lookups(self, request, model_admin):
            qs = model_admin.get_queryset(request)
            # Return a list of (id, name) for lookups. We return the language_id and the string format "Language Name (Count of Users)" as the name.
            return [(i, "{}({})".format(j, k)) for i, j, k in
                    qs.values_list('languages__id', 'languages__name').annotate(
                        user_count=Count('userprofile')).distinct().order_by(
                        'languages__name')]
    
        def queryset(self, request, queryset):
            if self.value():  # Use the lookup id we sent above; to filter
                return queryset.filter(languages__id=self.value())
    
    
    @admin.register(UserProfile):
    class UserProfileAdmin(admin.ModelAdmin):
        # ...
        list_filter = (UserProfileLanguageFilter,)
    

    I'd definitely encourage you to understand the Filter and also the Queryset better, if you choose to pick up code directly.