Django Admin过滤器添加双数值字段后无法获取值的问题求助
解决Django Admin数值范围过滤器的参数传递问题
我之前也碰到过一模一样的情况,默认的过滤器只支持单个参数,所以当你加了第二个输入框后,self.value()自然拿不到值了。下面是完整的解决方案,分成几个步骤来实现:
1. 自定义过滤器类
首先我们要写一个继承自SimpleListFilter的过滤器类,不在lookups里定义选项,而是自己写模板,然后从request.GET里直接获取两个字段的值:
from django.contrib import admin from django.utils.translation import gettext_lazy as _ class NumberRangeFilter(admin.SimpleListFilter): title = _('数值范围') parameter_name = 'is_within_range' # 仅作为过滤器标识,实际用不到它取值 def lookups(self, request, model_admin): # 返回空,因为我们用自定义模板展示输入框 return () def queryset(self, request, queryset): # 从request.GET里获取两个输入框的值 min_val = request.GET.get('is_within_min') max_val = request.GET.get('is_within_max') # 根据输入值组合过滤queryset,替换成你实际要过滤的字段(比如score) if min_val and max_val: return queryset.filter(score__gte=float(min_val), score__lte=float(max_val)) elif min_val: return queryset.filter(score__gte=float(min_val)) elif max_val: return queryset.filter(score__lte=float(max_val)) # 没填值就返回原queryset return queryset # 指定自定义模板路径 template = 'admin/number_range_filter.html'
2. 创建自定义过滤器模板
在你的Django项目的templates/admin目录下创建number_range_filter.html文件,内容如下(两个输入框的name要和过滤器类里取的键对应):
{% load i18n custom_filters %} <h3>{% blocktrans with title=title %}By {{ title }}{% endblocktrans %}</h3> <div class="form-row" style="display:flex; gap:8px; align-items:center;"> <input type="number" step="0.1" max="0.9" min="0.1" name="is_within_min" placeholder="最小值" value="{{ request.GET.is_within_min }}"> <span>至</span> <input type="number" step="0.1" max="0.9" min="0.1" name="is_within_max" placeholder="最大值" value="{{ request.GET.is_within_max }}"> <button type="submit" class="button">{% trans '过滤' %}</button> {% if request.GET.is_within_min or request.GET.is_within_max %} <a href="{{ request.path }}?{{ request.GET|remove:'is_within_min is_within_max' }}" class="button">{% trans '重置' %}</a> {% endif %} </div>
补充:实现重置按钮的过滤器
上面模板用到了remove模板过滤器来清除参数,需要自己实现:
在你的app的templatetags目录下创建custom_filters.py:
from django import template register = template.Library() @register.filter def remove(query_dict, keys): keys = keys.split() qd = query_dict.copy() for key in keys: qd.pop(key, None) return qd.urlencode()
3. 在Admin中注册过滤器
最后在你的ModelAdmin里添加这个过滤器:
@admin.register(YourModel) class YourModelAdmin(admin.ModelAdmin): list_filter = (NumberRangeFilter,) # 其他Admin配置...
为什么self.value()没用?
因为self.value()是SimpleListFilter用来获取当前过滤器对应的单个参数的值的,而我们现在是两个独立的参数,所以它自然返回None。直接从request.GET里取是最直接的方式,还能灵活处理两个输入框的各种组合情况。
内容的提问来源于stack exchange,提问作者mhs
相关产品推荐
相关产品推荐

