Django和jQuery,实现Ajax表格数据分页展示
1.需求描述
如果存在需要通过重新请求接口才能获取数据的功能,并且页面内容较长的情况下,在用户每次点击这类功能后会强制跳转至页面顶端可能会导致用户体验较差。我们建议希望实现的是:每当用户点击此类功能时能够立即加载相关数据,并且请求操作不会在前端呈现出来这样可以让用户体验更加流畅无阻
如果想无需刷新页面即可获取某一特定功能模块的数据,则可采用 AJAX 技术实现。具体而言,在用户点击某一功能模块按钮时会触发 AJAX 请求,在此过程中,AJAX 将向后端发送一些参数以获取更新的数据, 最终将更新显示的内容到前端界面。
为了解决问题:前端中的分页按钮具有特定样式,并且其样式基于后端返回的参数。为了确保不影响到正常的分页数据获取而不更改任何一个分页按钮的样式,在针对这一问题展开思考之后,默认的方法不再适用。因此,解决方案是将整个页面的部分代码通过Ajax技术重新渲染一次。
为了解决问题:前端中的分页按钮具有特定样式,并且其样式基于后端返回的参数。为了确保不影响到正常的分页数据获取而不更改任何一个分页按钮的样式,在针对这一问题展开思考之后,默认的方法不再适用。因此,解决方案是将整个页面的部分代码通过Ajax技术重新渲染一次。
2.将表格数据和分页功能的前端代码进行拆分
1)order_data_tables.html代码文件存放表格数据。
<table class="table-content table table-bordered table-hover">
<thead class="thead-dark">
<tr>
<th>品牌</th>
<th>商品名称</th>
<th>商品编号</th>
<th>订单编号</th>
<th>颜色</th>
<th>进价</th>
<th>零售价</th>
<th>净赚利润</th>
<th>数量</th>
</tr>
</thead>
<tbody style="font-size: 14px;">
{% for data in order_page_data %}
<tr>
<td>{{ data.brand }}</td>
<td>{{ data.commodity_name }}</td>
<td>{{ data.commodity_number }}</td>
<td>{{ data.order_number }}</td>
<td>{{ data.commodity_color }}</td>
<td>{{ data.purchasing_price }}</td>
<td>{{ data.retail_price }}</td>
<td>{{ data.profit }}</td>
<td>{{ data.quantity }}</td>
</tr>
{% endfor %}
</tbody>
</table>
2)order_data_page.html代码文件存放分页功能。
<ul class="pagination justify-content-center">
{% if order_page_data.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ order_page_data.previous_page_number }}" data-page={{ order_page_data.previous_page_number }}>上一页</a>
</li>
{% else %}
<li class="page-item disabled ">
<a class="page-link">上一页</a>
</li>
{% endif %}
{% for page in order_page_data.paginator.page_range %}
<li class="page-item {% if page == order_page_data.number %}active{% endif %}">
<a class="page-link" href="#" data-page="{{ page }}">{{ page }}</a>
</li>
{% endfor %}
{% if order_page_data.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ order_page_data.next_page_number }}" data-page={{ order_page_data.next_page_number }}>下一页</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link">下一页</a>
</li>
{% endif %}
</ul>
在order_data_page.html的总页面前端代码文件中仍然保留了用于展示数据表格以及分页功能的具体代码。

3.后端处理分页功能以及Ajax方式的请求
分页相对容易实现,其核心在于处理Ajax请求的过程,即当接收到Ajax请求时,调用render\_to\_string()方法来同时加载并返回两个前端文件的内容: order\_data\_tables.html 和 order\_data\_page.htm,它们分别包含表格数据以及页面布局的信息,这两者都将在接收到来自后端的数据包后被解码并展示在客户端界面上,完成一次完整的页面显示过程。
然后利用JsonResponse()方法将存储表格和分页数据的变量按JSON格式返回给前端
from django.http import HttpResponse, JsonResponse
from django.template.loader import render_to_string
def order_manage_beautiful(request):
order_data = OrderManage.objects.order_by('-id')
······
# 分页
order_pages = Paginator(order_data, 10)
order_page_num = int(request.GET.get("page", 1))
if order_page_num > order_pages.count:
order_page_num = 1
order_page_data = order_pages.page(order_page_num)
# 判断是否是Ajax请求,若为Ajax请求,则将表格数据和分页的前端代码进行渲染,并以Jason格式返回给前端
if request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest':
# render_to_string方法会将前端代码与后端参数渲染后,返回成html文本
order_table_html = render_to_string("order_data_tables.html", {"order_page_data": order_page_data})
order_page_html = render_to_string("order_data_page.html", {"order_page_data": order_page_data})
return JsonResponse({"order_table_html": order_table_html, "order_page_html": order_page_html})
return render(request, "order_manage_beautiful.html", {"is_file": is_file, "order_data": order_data, "order_page_data": order_page_data})
返回的Json如下所示。

4.编写Ajax请求分页数据的代码
4.1.为表格部分的代码绑定ID属性
将一个ID属性id="order_table"绑定到表格的上层div标签;当Ajax获取新数据时,在此标签中进行渲染以实现表格数据的动态更新。
<div class="card-body" id="order_table">
<table class="table-content table table-bordered table-hover">
<thead class="thead-dark">
<tr>
<th>品牌</th>
<th>商品名称</th>
<th>商品编号</th>
<th>订单编号</th>
<th>颜色</th>
<th>进价</th>
<th>零售价</th>
<th>净赚利润</th>
<th>数量</th>
</tr>
</thead>
<tbody style="font-size: 14px;">
{% for data in order_page_data %}
<tr>
<td>{{ data.brand }}</td>
<td>{{ data.commodity_name }}</td>
<td>{{ data.commodity_number }}</td>
<td>{{ data.order_number }}</td>
<td>{{ data.commodity_color }}</td>
<td>{{ data.purchasing_price }}</td>
<td>{{ data.retail_price }}</td>
<td>{{ data.profit }}</td>
<td>{{ data.quantity }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
4.2.为分页功能的代码绑定ID属性
依旧是分页功能的上层div标签中绑定:id="order_page"。
<div aria-label="Page navigation example" style="margin-top: 20px;" id="order_page">
<ul class="pagination justify-content-center">
{% if order_page_data.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ order_page_data.previous_page_number }}" data-page={{ order_page_data.previous_page_number }}>上一页</a>
</li>
{% else %}
<li class="page-item disabled ">
<a class="page-link">上一页</a>
</li>
{% endif %}
{% for page in order_page_data.paginator.page_range %}
<li class="page-item {% if page == order_page_data.number %}active{% endif %}">
<a class="page-link" href="#" data-page="{{ page }}">{{ page }}</a>
</li>
{% endfor %}
{% if order_page_data.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ order_page_data.next_page_number }}" data-page={{ order_page_data.next_page_number }}>下一页</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link">下一页</a>
</li>
{% endif %}
</ul>
</div>
4.3.编写Ajax实现分页数据的动态更新
当点击class为page-link并带有分页框标记时(操作触发了一个分页功能),JavaScript会导致JavaScript发起一个网络请求去访问端点]/order_manage_beautiful/接口,并发送一个page参数给服务器进行处理。当此操作成功完成后,服务器会返回相应的JSON数据给客户端展示页面内容。客户端会将响应中的order_table_html字段的内容加载到表格相关的div元素中,同时也会将响应中的order_page_html字段的内容加载到分页相关的div元素中以完成页面布局展示工作
$(document).on('click', '.page-link', function(e) {
e.preventDefault();
var page = $(this).data('page')
$.ajax({
url: '/order_manage_beautiful',
type: "GET",
data: {page: page},
success: function(data) {
// 渲染表格数据
$('#order_table').html(data.order_table_html);
// 渲染分页功能
$('#order_page').html(data.order_page_html);
}
});
});
4.4.效果展示

