如何在Django Admin中使用自定义过滤器筛选模型属性值
解决方案
要实现根据自定义过滤器的取值动态更新Admin页面中approved字段的显示值,你需要在Admin的自定义字段方法中获取当前过滤器的参数,并根据参数调整统计逻辑,具体步骤如下:
1. 保存请求对象到Admin实例
在ModelAdmin中重写changelist_view方法,将当前请求对象保存到实例中,这样后续的字段方法就能读取过滤器参数:
2. 重写approved方法添加时间范围过滤
在approved方法中读取过滤器的timeframe参数,根据不同选项对关联的ModelRecordRelation查询集添加日期过滤条件,再返回统计数量。
修改后的完整admin.py代码
from django.utils import timezone from django.contrib import admin from .models import Model, ModelRecordRelation class TimeFrameFilter(SimpleListFilter): title = '时间范围' parameter_name = 'timeframe' def lookups(self, request, model_admin): return [ ('Today', '今日'), ('ThisWeek', '本周'), ] def queryset(self, request, queryset): # 无需过滤查询集,仅提供过滤器选项 return queryset class ModelAdmin(admin.ModelAdmin): list_display = ['created', 'updated', 'approved'] def changelist_view(self, request, extra_context=None): # 保存当前请求到Admin实例 self.request = request return super().changelist_view(request, extra_context) def approved(self, obj): # 获取过滤器选择的时间范围 timeframe = self.request.GET.get('timeframe') # 基础查询:关联的已审批记录 record_query = ModelRecordRelation.objects.filter(model_id=obj.id, status='A') # 根据时间范围过滤 if timeframe == 'Today': today = timezone.now().date() record_query = record_query.filter(created__date=today) elif timeframe == 'ThisWeek': # 计算本周起始(周一)和结束(周日)日期 today = timezone.now().date() start_week = today - timezone.timedelta(days=today.weekday()) end_week = start_week + timezone.timedelta(days=6) record_query = record_query.filter(created__date__range=(start_week, end_week)) return record_query.count() approved.short_description = '已审批数量' # 注意:该字段为动态计算值,无法通过admin_order_field实现排序(需依赖查询集annotate,与需求冲突)
关键说明
- 假设
ModelRecordRelation模型包含created日期字段用于判断时间范围,如果你的实际字段是updated或其他名称,需替换代码中对应的字段名。 - 原模型中的
_approved属性可保留(用于其他场景的全局统计),Admin页面不再依赖它,而是使用自定义的approved方法。 - 关于排序:由于该字段是动态计算的,无法直接通过
admin_order_field实现排序——如果需要排序,必须在查询集中提前用annotate计算统计值,但这会修改模型查询集,与你的需求冲突,因此排序功能暂无法实现。
内容的提问来源于stack exchange,提问作者sasha
相关产品推荐
相关产品推荐

