JavaScript中使用DTL(Django模板语言)for循环赋值写法咨询
现有实现的问题
你的写法完全错误,核心问题如下:
- 执行时机完全错位:Django模板的
{% for %}是服务端渲染阶段运行的,页面发给浏览器时,模板标签已经被替换成静态内容——如果你的部门id是1、2、3,最终浏览器拿到的JS代码里这一段会变成value="' + '123' + '"。而DataTable的render函数是前端每渲染一行就执行一次,最后所有复选框的value都会是所有id拼接成的同一个长字符串,完全拿不到每行对应的正确id。 - 存在语法和安全隐患:直接把模板变量输出到JS字符串中没有做转义,如果id包含引号、换行、
<script>等特殊内容,轻则直接触发JS语法报错,重则导致XSS注入漏洞。另外你贴的代码里name=属性后面直接断行,本身就有语法问题。 - 不符合HTML规范:所有复选框都写死了相同的
id="chkuser",HTML要求id全局唯一,后续用ID选择器取元素时只会拿到第一个复选框,出现逻辑异常。
更合理的实现方案
核心思路:不要在JS字符串拼接逻辑里混写Django模板循环标签,把数据和渲染逻辑分离,推荐两种成熟写法:
方案1:用json_script安全传递数据(最推荐)
Django提供了json_script模板标签,可以安全地把后端数据集序列化成JSON,避免转义和XSS问题,步骤如下:
- 先在模板里(JS代码外部)输出序列化好的部门数据:
{{ departmentData|json_script:"dept-list" }}
- 编写DataTable配置逻辑,直接使用解析好的数据,从当前行数据里取id,不需要额外循环:
// 读取序列化好的部门数据 const deptList = JSON.parse(document.getElementById('dept-list').textContent); var table = $('.checkbox-datatable').DataTable({ scrollCollapse: true, autoWidth: false, responsive: true, lengthMenu: [[10, 25, 50, -1], [10, 25, 50, "All"]], language: { info: "_START_-_END of TOTAL_ entries", searchPlaceholder: "Search", paginate: { next: '<i class="ion-chevron-right"></i>', previous: '<i class="ion-chevron-left"></i>' } }, // 直接传入部门数据作为数据源 data: deptList, // 配置列和数据源字段的对应关系,按你的实际业务字段调整 columns: [ { data: 'id' }, // 第一列是复选框 { data: 'name' }, // 后续列按实际部门字段补充,比如部门名称、负责人、创建时间等 // 其他列配置... ], columnDefs: [{ targets: 0, searchable: false, orderable: false, className: 'dt-body-center', render: function (data, type, full, meta){ // full就是当前行对应的部门对象,直接取id即可,加行索引保证id唯一 return `<div class="dt-checkbox"> <input type="checkbox" name="id[]" id="chkuser-${meta.row}" value="${full.id}" /> <span class="dt-checkbox-label"></span> </div>`; } }], order: [[1, 'asc']] });
方案2:AJAX异步加载数据场景
如果你的DataTable是通过AJAX从后端接口拉取分页数据,不需要提前把全量数据渲染到页面,只需要保证后端接口返回的每条数据都包含id字段,render函数里直接用full.id取值即可,不需要在前端写任何循环遍历全量数据的逻辑。
注意:不要为了省事直接在JS里写
const deptList = {{ departmentData|safe }},这种写法如果数据里包含</script>等特殊字符会直接破坏页面结构,安全风险很高,优先用json_script的写法。
内容的提问来源于stack exchange,提问作者user18963243
相关产品推荐
相关产品推荐

