Django中DataTable无法重新初始化及JSON数据注入问题求助
问题分析
你的代码存在三个核心问题:
- 错误使用Django循环包裹脚本:
company是JSON字符串而非可迭代对象,{% for row in company %}会把JSON拆成单个字符循环,生成N个重复的<script>标签,每个标签都初始化一次DataTable,直接触发"Cannot reinitialise DataTable"报错。 - 数据格式不匹配:Django的
serializers.serialize()返回的是包含model、pk、fields的嵌套JSON,而DataTables需要的是直接包含字段的扁平对象数组。 - Columns配置与实际数据/表格列不对应:表格列是
Name、Code、Address等,但JS中columns用的是full_name、email等不存在的字段,导致数据无法渲染。
正确解决方案
提供两种常用实现方式,根据数据量选择:
方式一:直接将数据注入模板(适合小数据量)
1. 修改Views.py,构造DataTables兼容的数据格式
不用serializers.serialize,直接提取模型字段为扁平字典列表:
from main.models import Company def company(request): # 按需提取字段,确保和表格列对应 company_list = list(Company.objects.order_by('name').values( 'id', 'name', 'code', 'address', 'remarks', 'status' )) context = { 'company_list': company_list, } return render(request, 'admin/company.html', context)
2. 修改模板中的JS代码
去掉错误循环,将注入的数据直接传给DataTables的data选项,同时修正columns配置匹配实际字段:
{% block footer_scripts %} <script> $(function () { var dt_basic_table = $('.datatables-basic'), dt_basic; if (dt_basic_table.length) { dt_basic = dt_basic_table.DataTable({ // 用|safe确保JSON格式不被转义 data: {{ company_list|safe }}, columns: [ { data: null }, // 响应式控制列 { data: null }, // 复选框列 { data: 'id' }, // 隐藏的ID列 { data: 'name' }, // 对应表格Name列 { data: 'code' }, // 对应表格Code列 { data: 'address' }, // 对应表格Address列 { data: 'remarks' }, // 对应表格Remarks列 { data: 'status' }, // 对应表格Status列 { data: null } // 操作列 ], columnDefs: [ { className: 'control', orderable: false, searchable: false, responsivePriority: 2, targets: 0, render: function () { return ''; } }, { targets: 1, orderable: false, searchable: false, responsivePriority: 3, checkboxes: true, render: function () { return '<input type="checkbox" class="dt-checkboxes form-check-input">'; }, checkboxes: { selectAllRender: '<input type="checkbox" class="form-check-input">' } }, { targets: 2, searchable: false, visible: false }, { // 自定义Name列渲染逻辑 targets: 3, responsivePriority: 4, render: function (data, type, full) { return `<div class="d-flex flex-column"> <span class="emp_name text-truncate">${full.name}</span> <small class="emp_post text-truncate text-muted">${full.code}</small> </div>`; } }, { responsivePriority: 1, targets: 4 }, { // 自定义Status列渲染,根据实际status值调整映射 targets: -2, render: function (data, type, full) { var statusMap = { 1: { title: '活跃', class: 'bg-label-primary' }, 2: { title: '禁用', class: 'bg-label-danger' }, // 扩展其他状态映射 }; if (!statusMap[data]) return data; return `<span class="badge ${statusMap[data].class}">${statusMap[data].title}</span>`; } }, { // 操作列渲染 targets: -1, render: function (data, type, full) { return `<div class="dropdown"> <button class="btn btn-sm btn-icon dropdown-toggle" type="button" data-bs-toggle="dropdown"> <i class="bx bx-dots-vertical-rounded"></i> </button> <div class="dropdown-menu dropdown-menu-end"> <a class="dropdown-item" href="#">编辑</a> <a class="dropdown-item" href="#">删除</a> </div> </div>`; } } ] }); $('div.head-label').html('<h5 class="card-title mb-0">公司列表</h5>'); } }); </script> {% endblock footer_scripts %}
方式二:通过AJAX请求API加载数据(适合大数据量)
1. 添加API视图和路由
Views.py
新增返回JSON数据的视图:
from django.http import JsonResponse from main.models import Company def company_data(request): company_list = list(Company.objects.order_by('name').values( 'id', 'name', 'code', 'address', 'remarks', 'status' )) # DataTables要求返回包含data键的JSON对象 return JsonResponse({'data': company_list})
urls.py
添加对应路由:
from django.urls import path from . import views urlpatterns = [ path('company/', views.company, name='company'), path('company/data/', views.company_data, name='company-data'), ]
2. 修改模板中的JS代码
将ajax选项指向API路由,其余配置和方式一一致:
{% block footer_scripts %} <script> $(function () { var dt_basic_table = $('.datatables-basic'), dt_basic; if (dt_basic_table.length) { dt_basic = dt_basic_table.DataTable({ // 用Django url标签生成API地址 ajax: '{% url "company-data" %}', columns: [ { data: null }, { data: null }, { data: 'id' }, { data: 'name' }, { data: 'code' }, { data: 'address' }, { data: 'remarks' }, { data: 'status' }, { data: null } ], // 复制方式一中的columnDefs配置 columnDefs: [ // ... 省略重复代码 ] }); $('div.head-label').html('<h5 class="card-title mb-0">公司列表</h5>'); } }); </script> {% endblock footer_scripts %}
关键注意事项
- 确保
columns的data值和模型提取的字段名完全一致。 - 若
status字段取值和示例不同,务必调整statusMap的映射关系。 - 单个表格只需初始化一次,禁止用循环包裹初始化脚本。
内容的提问来源于stack exchange,提问作者marivic valdehueza
相关产品推荐
相关产品推荐

