DataTables 在 CRUD 操作上刷新 Django Ajax 数据
Posted
技术标签:
【中文标题】DataTables 在 CRUD 操作上刷新 Django Ajax 数据【英文标题】:DataTables Refresh Django Ajax Data on CRUD Operations 【发布时间】:2018-07-16 20:01:29 【问题描述】:我有一个带有 Analytic
模型的 Django 项目。此模型是分析列表。它有一个ForeignKeyField
和一个ManyToMany
字段。最终目标是让用户转到一个 URL,他们可以在其中查看 DataTable 中的分析列表、创建新分析、编辑分析和删除分析。使用本教程:https://simpleisbetterthancomplex.com/tutorial/2016/11/15/how-to-implement-a-crud-using-ajax-and-json.html,我在常规的 Bootstrap HTML 表中完成了所有这些目标(即不在 DataTable 中)。
当我尝试在混合中引入 DataTable 时,我发现我的 DataTable 是从 HTML/DOM 源中提取的,因此除非刷新页面,否则它不会更新。所以我意识到我需要将 DataTable 配置为最初从 HTML/DOM 中提取然后从 AJAX 中提取,或者我需要最初使用 Ajax 作为源。
事实证明,普通的 Django 在序列化 ManyToMany
字段方面做得不好,所以我选择使用 DRF 来序列化我的 Analytic
模型。这在一定程度上有效:JSON 输出看起来不错,结果显示在我的 DataTable 中。但是,当进行 Ajax 调用时,数据仍然没有更新。此外,DataTables 并不允许内嵌按钮进行编辑/删除,这就是为什么必须首先将这些按钮手动写入 HTML。
问题:当执行 Ajax CRUD 操作时,如何强制来自 HTML/DOM 的 DataTable 更新其数据而不刷新页面?
views.py:
def analytic_list(request):
analytics = Analytic.objects.all().select_related('analyticCategory').prefetch_related('dataSources')
return render(request, 'analytics/analytic_list.html', 'analytics':analytics)
def save_analytic_form(request, form, template_name):
data = dict()
if request.method == 'POST':
if form.is_valid():
form.save()
data['form_is_valid'] = True
analytics = Analytic.objects.all()
data['html_analytic_list'] = render_to_string('analytics/includes/partial_analytic_list.html',
'analytics': analytics
)
else:
data['form_is_valid'] = False
context = 'form': form
data['html_form'] = render_to_string(template_name, context, request=request)
return JsonResponse(data)
def analytic_create(request):
if request.method == 'POST':
form = AnalyticForm(request.POST)
else:
form = AnalyticForm()
return save_analytic_form(request, form, 'analytics/includes/partial_analytic_create.html')
def analytic_update(request, pk):
analytic = get_object_or_404(Analytic, pk=pk)
if request.method == 'POST':
form = AnalyticForm(request.POST, instance=analytic)
else:
form = AnalyticForm(instance=analytic)
return save_analytic_form(request, form, 'analytics/includes/partial_analytic_update.html')
def analytic_delete(request, pk):
analytic = get_object_or_404(Analytic, pk=pk)
data = dict()
if request.method == 'POST':
analytic.delete()
data['form_is_valid'] = True # This is just to play along with the existing code
analytics = Analytic.objects.all()
data['html_analytic_list'] = render_to_string('analytics/includes/partial_analytic_list.html',
'analytics': analytics
)
else:
context = 'analytic': analytic
data['html_form'] = render_to_string('analytics/includes/partial_analytic_delete.html',
context,
request=request,
)
return JsonResponse(data)
urls.py:
url(r'^dataanalytics/analytics/$', views.analytic_list, name='analytic_list'),
url(r'^dataanalytics/analytics/create/$', views.analytic_create, name='analytic_create'),
url(r'^dataanalytics/analytics/(?P<pk>\d+)/update/$', views.analytic_update, name='analytic_update'),
url(r'^dataanalytics/analytics/(?P<pk>\d+)/delete/$', views.analytic_delete, name='analytic_delete'),
analytic_list.html:
% block content %
<!-- BUTTON TO TRIGGER THE ACTION -->
<p>
<button type="button"
class="btn btn-primary js-create-analytic"
data-url="% url 'analytic_create' %">
<span class="fa fa-plus"></span>
New analytic
</button>
</p>
<table class="table table-hover table-sm display responsive" cellspacing="0" id="analytic-table">
<thead>
<tr>
<th class="all align-top">#</th>
<th class="all align-top">Name</th>
<th class="all align-top">Description</th>
<th class="all align-top">Category</th>
<th class="all align-top">Type</th>
<th class="all align-top">Format</th>
<th class="all align-top">Data Source(s)</th>
<th class="all align-top"></th>
<th class="none">Created By</th>
<th class="none">Created Date</th>
<th class="none">Modified By</th>
<th class="none">Modified Date</th>
</tr>
</thead>
<!-- <tbody>
% include 'analytics/includes/partial_analytic_list.html' %
</tbody> -->
</table>
<!-- THE MODAL WE WILL BE USING -->
<div class="modal fade" id="modal-analytic">
<div class="modal-dialog">
<div class="modal-content">
</div>
</div>
% endblock %
partial_analytic_list.html:
% for analytic in analytics %
<tr>
<td> analytic.id </td>
<td> analytic.analytic </td>
<td> analytic.analyticDescription </td>
<td> analytic.analyticCategory </td>
<td> analytic.analyticType </td>
<td> analytic.analyticFormat </td>
<td>
% for data_source in analytic.dataSources.all %
data_source
% endfor %
</td>
<td>
<button type="button"
class="btn btn-warning btn-sm js-update-analytic"
data-url="% url 'analytic_update' analytic.id %">
<span class="fa fa-pencil-alt"></span>
</button>
<button type="button"
class="btn btn-danger btn-sm js-delete-analytic"
data-url="% url 'analytic_delete' analytic.id %">
<span class="fa fa-trash-alt"></span>
</button>
</td>
<td> analytic.createdBy </td>
<td> analytic.createdDateTime </td>
<td> analytic.modifiedBy </td>
<td> analytic.modifiedDateTime </td>
</tr>
% empty %
<tr>
<td colspan="7" class="text-center bg-warning">No analytic</td>
</tr>
% endfor %
analytics.js:
$(function ()
/* Functions */
var loadForm = function ()
var btn = $(this);
$.ajax(
url: btn.attr("data-url"),
type: 'get',
dataType: 'json',
beforeSend: function ()
$("#modal-analytic").modal("show");
,
success: function (data)
$("#modal-analytic .modal-content").html(data.html_form);
);
;
var saveForm = function ()
var form = $(this);
$.ajax(
url: form.attr("action"),
data: form.serialize(),
type: form.attr("method"),
dataType: 'json',
success: function (data)
if (data.form_is_valid)
$("#analytic-table tbody").html(data.html_analytic_list);
$("#modal-analytic").modal("hide");
else
$("#modal-analytic .modal-content").html(data.html_form);
);
return false;
;
/* Binding */
// Create analytic
$(".js-create-analytic").click(loadForm);
$("#modal-analytic").on("submit", ".js-analytic-create-form", saveForm);
// Update analytic
$("#analytic-table").on("click", ".js-update-analytic", loadForm);
$("#modal-analytic").on("submit", ".js-analytic-update-form", saveForm);
// Delete analytic
$("#analytic-table").on("click", ".js-delete-analytic", loadForm);
$("#modal-analytic").on("submit", ".js-analytic-delete-form", saveForm);
var table = $('#analytic-table').DataTable(
);
);
【问题讨论】:
【参考方案1】:我假设您在谈论 JQuery 数据表。你是如此接近,只是缺少一些位!您需要销毁并重新初始化表,无需使用 .draw()。如下所示:
阿贾克斯:
var saveForm = function ()
var form = $(this);
$.ajax(
url: form.attr("action"),
data: form.serialize(),
type: form.attr("method"),
dataType: 'json',
success: function (data)
if (data.form_is_valid)
$("#modal-analytic").modal("hide"); //hide it first if you want
$("#analytic-table").DataTable().destroy(); //this will flush DT's cache
$("#analytic-table tbody").html(data.html_analytic_list); // replace the html
$("#analytic-table").DataTable(); // re-initialize the DataTable
else
$("#modal-analytic .modal-content").html(data.html_form);
);
return false;
;
干得好,祝你好运!迟到的答案,但也许它会对某人有所帮助。
【讨论】:
【参考方案2】:看起来您的表格更新正在使用这个:
$("#analytic-table tbody").html(data.html_analytic_list);
您需要使用 Datatables API 来更新 Datatables 数据。由于您直接更新 HTML 数据表,因此不知道更新。一种选择是使用 rows().invalidate() 之类的东西在您使用 HTML 方法更新后让 Datatables 更新其数据缓存。
但是更好的选择是对多行使用rows.add(),对单行使用row.add()。
由于您的数据中似乎有 tr
元素,因此您可以分别对一行或多行使用类似的内容:
table.row.add($(data.html_analytic_list)).get(1)).draw();
table.rows.add($(data.html_analytic_list))).draw();
【讨论】:
以上是关于DataTables 在 CRUD 操作上刷新 Django Ajax 数据的主要内容,如果未能解决你的问题,请参考以下文章
jQuery 插件 (DataTables) 仅在页面刷新时正确加载
如何使用 INNER JOIN 改进我的 php sub_array 代码以在 DataTables 上显示数据?
.Net MVC&&datatables.js&&bootstrap做一个界面的CRUD有多简单