在InputFilter类应用SimpleListFilter时出现HTML内容问题求助
解决Django Admin InputFilter出现HTML内容的问题
看起来你在自定义Django Admin的InputFilter时遇到了过滤器渲染出HTML内容的问题,这通常是因为用户提供的文本(比如主管名称、ERN)包含HTML特殊字符,且没有在模板或代码中进行正确转义导致的。下面是具体的解决方案:
1. 核心原因分析
当你的过滤器选项中包含<、>、&这类HTML特殊字符时,如果没有转义,浏览器会把它们当成HTML标签解析,从而出现异常的HTML内容显示。我们需要在代码生成选项和模板渲染两个环节都确保文本被正确转义。
2. 代码层面修改
首先在过滤器代码中对动态生成的选项文本进行转义,同时确保choices方法返回的内容也被处理:
from django.utils.html import escape from django.contrib import admin class InputFilter(admin.SimpleListFilter): template = 'nyc-theme/lms/templates/admin/course_enrollment/input_filter.html' def lookups(self, request, model_admin): # 占位实现,过滤器显示必需 return ((),) def choices(self, changelist): # 仅获取“全部”选项 all_choice = next(super().choices(changelist)) all_choice['query_parts'] = ( (k, v) for k, v in changelist.get_filters_params().items() if k != self.parameter_name ) # 确保“全部”选项的文本也被转义(默认是安全的,但做个保障) all_choice['label'] = escape(all_choice['label']) yield all_choice class SupervisorNameFilter(InputFilter): title = 'Supervisor Name' parameter_name = 'supervisor' def lookups(self, request, model_admin): kwargs = { 'profile__supervisor_name__isnull': False } if 'profile__agency__id__exact' in request.GET: agency_id = request.GET['profile__agency__id__exact'] kwargs['profile__agency__id__exact'] = agency_id if 'division' in request.GET: division_id = request.GET['division'] kwargs['profile__division__id__exact'] = division_id users = model_admin.model.objects.filter(**kwargs).distinct() # 对返回的ERN和主管名称进行HTML转义,避免特殊字符被当成HTML渲染 return [ (escape(user.profile.supervisor_ernumber), escape(user.profile.supervisor_name)) for user in users ] def queryset(self, request, queryset): if self.value(): # 查询时不需要转义,数据库会处理原始文本 return queryset.filter(profile__supervisor_name__icontains=self.value()) class SupervisorERNFilter(InputFilter): title = 'Supervisor ERN' parameter_name = 'ern' def queryset(self, request, queryset): if self.value(): return queryset.filter(profile__supervisor_ernumber__icontains=self.value())
3. 模板层面修改
检查你的自定义模板input_filter.html,确保所有动态渲染的文本都使用|escape过滤器:
<!-- nyc-theme/lms/templates/admin/course_enrollment/input_filter.html --> {% load i18n %} <h3>{{ title|escape }}</h3> <ul class="admin-filter"> {% if choices %} <li> <select name="{{ parameter_name|escape }}"> {% for choice in choices %} <option value="{{ choice.value|escape }}"{% if choice.selected %} selected{% endif %}> {{ choice.label|escape }} </option> {% endfor %} </select> </li> {% endif %} <!-- 如果是输入框类型的过滤器(比如ERN过滤器),也要转义输入值 --> {% if parameter_name == 'ern' %} <li> <input type="text" name="{{ parameter_name|escape }}" value="{{ current_value|escape }}" placeholder="{% trans 'Enter Supervisor ERN' %}"> </li> {% endif %} </ul>
4. 关键注意点
- 转义只需要在渲染到HTML的时候做,数据库查询时不需要转义,Django的ORM会自动处理参数安全。
- 如果你的主管名称/ERN是信任的内容(不会包含恶意HTML),也可以使用
mark_safe,但不推荐,因为无法保证未来数据不会出现特殊字符。
内容的提问来源于stack exchange,提问作者Sourav
相关产品推荐
相关产品推荐

