如何在Django Admin筛选面板中显示各分类的条目数量?
在Django Admin筛选面板中为多对多筛选添加条目数量
我刚好折腾过这个需求,其实核心就是自定义一个筛选器,替代默认的多对多字段筛选器,在生成选项的时候把关联的条目数量带上就行,具体步骤如下:
1. 自定义带数量的语言筛选器
首先我们要写一个继承自admin.SimpleListFilter的筛选器类,它会负责生成带数量的筛选选项,以及处理筛选逻辑:
from django.contrib import admin from django.db.models import Count from .models import UserProfile, Language class LanguageWithCountFilter(admin.SimpleListFilter): # 筛选器在面板上显示的标题 title = '掌握语言' # 用于URL参数的名称,避免和其他字段冲突 parameter_name = 'filter_language' def lookups(self, request, model_admin): # 一次性查询所有语言,并统计每个语言关联的UserProfile数量 # 这里的'userprofile'是Django自动生成的反向关联名称(模型名小写),如果你的related_name改了要对应替换 language_list = Language.objects.annotate( user_count=Count('userprofile') ).order_by('name') # 把每个语言的名称和数量拼接成选项文本 return [ (lang.id, f"{lang.name} ({lang.user_count})") for lang in language_list ] def queryset(self, request, queryset): # 处理筛选逻辑:如果选中了某个语言ID,就过滤出关联该语言的用户 selected_lang_id = self.value() if selected_lang_id: return queryset.filter(languages__id=selected_lang_id) # 没选中的话返回全部结果 return queryset
2. 在Admin配置中使用自定义筛选器
接下来修改你的UserProfileAdmin配置,把原来list_filter里的languages替换成我们刚写的筛选器类:
@admin.register(UserProfile) class UserProfileAdmin(admin.ModelAdmin): # 保留你原来的其他配置,比如list_display、search_fields等 # ... # 替换默认的languages筛选器为自定义的带数量版本 list_filter = (LanguageWithCountFilter,) # 如果原来还有其他筛选字段,直接追加进去就行,比如: # list_filter = ('is_active', LanguageWithCountFilter,)
注意事项
- 反向关联名称:如果你的
UserProfile.languages字段设置了related_name参数(比如languages = models.ManyToManyField(Language, blank=True, related_name='language_users')),那在Count()里要换成对应的名称,也就是Count('language_users')。 - 性能优化:用
annotate+Count的方式是一次性查询所有语言和对应的数量,比循环每个语言单独查count()要高效得多,数据量大的时候差异很明显。
这样配置完之后,刷新Admin页面,你就能看到筛选面板里的每个语言选项后面都带上了对应的用户数量啦!
内容的提问来源于stack exchange,提问作者nbeuchat
相关产品推荐
相关产品推荐

