Django模板页面重载后如何保留筛选器选中值?
Django页面重载后保留筛选器选中值的解决方案
问题背景
我在Django模板中尝试实现页面重载后保留筛选器的选中值,但下面两种写法都无效:
第一种模板代码
<label for="structDivisions">Structural divisions</label> <select id="structDivisions" class="form-select form-select-sm" name="struct_division"> {% for SD in struct_divisions %} <option value="{{ SD.id }}" {% if SD.id == struct_division.id %} selected {% endif %}>{{ SD }}</option> {% endfor %} </select>
第二种模板代码
<label for="structDivisions">Structural divisions</label> <select id="structDivisions" class="form-select form-select-sm" name="struct_division"> {% for SD in struct_divisions %} <option value="{{ SD }}" {% if SD == struct_division.select %} selected {% endif %}>{{ SD }}</option> {% endfor %} </select>
视图函数代码(筛选功能正常但无法保留选中值)
def ReportsFilterView(request): user = get_current_user(request) qs = CompletedWork.objects.filter(checked_by_head=True).filter( Q(worker__struct_division__head=user) | Q(worker__struct_division__management_unit__head=user) | Q(worker__struct_division__curator=user) | Q(worker__struct_division__management_unit__curator=user) ) struct_divisions = StructuralDivisions.objects.filter( Q(head=user) | Q(management_unit__head=user) | Q(curator=user) | Q(management_unit__curator=user) ) workers = CustomUser.objects.filter( Q(struct_division__head=user) | Q(struct_division__management_unit__head=user) | Q(struct_division__curator=user) | Q(struct_division__management_unit__curator=user) ) workstype = WorksType.objects.filter( Q(available_to__head=user) | Q(available_to__curator=user) ).distinct() work_notes_contains_query = request.GET.get('work_notes_contains') work_scope_min = request.GET.get('work_scope_min') work_scope_max = request.GET.get('work_scope_max') period_min = request.GET.get('period_min') period_max = request.GET.get('period_max') struct_division = request.GET.get('struct_division') # special for worker worker = request.GET.get('worker') if worker and worker != 'Choose...': middle_name = None try: last_name, first_name, middle_name = worker.split() try: worker_get_id = CustomUser.objects.get(last_name=last_name, first_name=first_name, middle_name=middle_name) except ValueError: worker_get_id = None except ValueError: last_name, first_name = worker.split() worker_get_id = CustomUser.objects.get(last_name=last_name, first_name=first_name) work_done = request.GET.get('work_done') if is_valid_query_param(work_notes_contains_query): qs = qs.filter(work_notes__icontains=work_notes_contains_query) if is_valid_query_param(work_scope_min): qs = qs.filter(work_scope__gte=work_scope_min) if is_valid_query_param(work_scope_max): qs = qs.filter(work_scope__lte=work_scope_max) if is_valid_query_param(period_min): qs = qs.filter(period__date__gte=period_min) if is_valid_query_param(period_max): qs = qs.filter(period__date__lte=period_max) if is_valid_query_param(struct_division) and struct_division != 'Choose...': qs = qs.filter(worker__struct_division__name=struct_division) if worker: if is_valid_query_param(worker) and worker != 'Choose...': qs = qs.filter(worker=worker_get_id) if is_valid_query_param(work_done) and work_done != 'Choose...': qs = qs.filter(work_done__name=work_done).filter( Q(worker__struct_division__head=user) | Q(worker__struct_division__management_unit__head=user) | Q(worker__struct_division__curator=user) | Q(worker__struct_division__management_unit__curator=user) ) context = { 'queryset': qs, 'struct_divisions': struct_divisions, 'workers': workers, 'workstype': workstype, } if 'button_export' in request.GET: return export_report(request) return render(request, 'reports_related_struct_unit.html', context)
解决方案
核心问题是未将当前选中的筛选参数传入模板上下文,同时模板中的判断逻辑存在类型不匹配的问题,按以下步骤修改即可解决:
步骤1:更新视图函数,传递筛选参数到上下文
在视图的context字典中,添加所有当前获取到的GET筛选参数:
context = { 'queryset': qs, 'struct_divisions': struct_divisions, 'workers': workers, 'workstype': workstype, # 新增:传递所有筛选参数到模板 'work_notes_contains': work_notes_contains_query, 'work_scope_min': work_scope_min, 'work_scope_max': work_scope_max, 'period_min': period_min, 'period_max': period_max, 'selected_struct_division': struct_division, 'selected_worker': worker, 'selected_work_done': work_done, }
步骤2:修正模板下拉框的选中判断逻辑
针对struct_division下拉框,根据传入的selected_struct_division值判断选中状态,注意处理类型匹配问题:
情况1:下拉框选项值用SD.id
request.GET获取的是字符串类型,而SD.id是整数,需要转成字符串再比较:
<label for="structDivisions">Structural divisions</label> <select id="structDivisions" class="form-select form-select-sm" name="struct_division"> <option value="Choose...">Choose...</option> {% for SD in struct_divisions %} <option value="{{ SD.id }}" {% if SD.id|stringformat:"s" == selected_struct_division %} selected {% endif %}>{{ SD }}</option> {% endfor %} </select>
情况2:下拉框选项值用SD.name(和视图中筛选逻辑匹配)
直接比较字符串即可:
<label for="structDivisions">Structural divisions</label> <select id="structDivisions" class="form-select form-select-sm" name="struct_division"> <option value="Choose...">Choose...</option> {% for SD in struct_divisions %} <option value="{{ SD.name }}" {% if SD.name == selected_struct_division %} selected {% endif %}>{{ SD }}</option> {% endfor %} </select>
步骤3:其他筛选控件的适配示例
- 文本输入框:直接设置
value属性
<input type="text" name="work_notes_contains" value="{{ work_notes_contains|default:'' }}">
- 数值范围输入框:
<input type="number" name="work_scope_min" value="{{ work_scope_min|default:'' }}"> <input type="number" name="work_scope_max" value="{{ work_scope_max|default:'' }}">
额外优化:统一处理默认值
在视图中给参数设置默认值,避免模板出现None:
struct_division = request.GET.get('struct_division', 'Choose...') worker = request.GET.get('worker', 'Choose...') # 其他参数同理设置默认值
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

