16. 你很勇哦,这么点数据就敢用异步加载?
Posted 梦想橡皮擦
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了16. 你很勇哦,这么点数据就敢用异步加载?相关的知识,希望对你有一定的参考价值。
爬虫训练场项目第16课,异步AJAX加载学校清单。
爬虫训练场,让天下没有失效的爬虫,2023年橡皮擦最新专栏。
项目仓库地址 :https://gitcode.net/hihell/spider_playground
博客清单:https://pachong.vip/blog
文章目录
Bootstrap 实现 ajax 请求
本篇博客的核心是使用 Bootstrap 中的 javascript 插件发送 Ajax 请求,下面先看一个示例,展示如何使用 Bootstrap 中的 $.ajax()
方法发送 AJAX 请求,这里使用的 $.ajax()
由 jQuery 插件实现,所以提前在模板文件中进行一下导入。
https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.6.0.min.js
实现本步骤操作,需要在 app/templates/school
目录中新增 ajax_list.html
文件,然后输入下述代码。
% extends "base.html" %
% block script %
<script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
</script>
% endblock script %
% block content %
% endblock %
该文件继承了 base.html
文件,然后在其 script
块中,可以编写JS代码。
使用 jQuery 发送 Ajax 请求的示例代码如下所示,后续将在此基础上实现请求和渲染逻辑。
$.ajax(
type: "POST",
url: "/path/to/server",
data:
key1: "value1",
key2: "value2"
,
success: function(response)
console.log("AJAX request succeeded!");
,
error: function(error)
console.log("AJAX request failed: " + error);
);
接下来将刚刚的文件,绑定到视图函数中,代码编写到 school/index.py
中,如下所示。
@s.route('ajax_list')
def ajax_list():
page = 1 # 初始化第一页数据
pagination = pagination_object(page)
return render_template('school/ajax_list.html', pagination=pagination)
这里将分页对象的创建的函数进行了封装,便于后续重复使用,pagination_object()
函数内容如下所示。
def pagination_object(page=1):
# schools = School.query.all()
query = School.query
total = query.count() # 获取数据总量
pagination = Pagination(page, total) # 获取分页对象详细参数
if total != 0:
data_list = query.offset(pagination["offset"]).limit(pagination["page_size"]).all()
else:
data_list = []
pagination["data_list"] = data_list
return pagination
使用 AJAX 渲染数据重点在 JS 部分,核心操作为分页请求,所以首次进入页面,需要对第一页数据进行渲染,补充 ajax_list.html
首次渲染部分代码。
<div class="container" id="school_list">
% for school in pagination.data_list %
<div class="row mt-3">
<div class="col">
<div class="d-flex">
<div class="flex-shrink-0">
<a href="#">
<img class="rounded-pill img-thumbnail" width="64" height="64" src="school.pic" alt="">
</a>
</div>
<div class="flex-grow-1 ms-3">
<h5 class="float-start pe-3">school.name</h5>
<p class="ms-3">
% for fea in school.feature.split(',') %
<span class="badge rounded-pill bg-primary">fea</span>
% endfor %
</p>
<p><em>所在省市:<span class="text-black-50">school.province -- school.city</span></em></p>
</div>
</div>
</div>
</div>
% endfor %
</div>
<div class="container">
<div class="row">
<div class="col">
<span class="text-dark float-end align-middle"
style="line-height: 40px;">合计 pagination.total 条数据</span>
<ul class="pagination float-end">
<li class="page-item prev" page="pagination.prev_page">
<a class="page-link" href="#">上一页</a>
</li>
<li class="page-item next" page=" pagination.next_page "><a class="page-link"
href="#">下一页</a>
</li>
</ul>
</div>
</div>
</div>
上述代码进行了两部分修改,第一个是给 .container
类绑定的 DIV 增加了一个 ID 值,第二个修改是给分页 <li>
标签增加了自定义属性 page
,并分别绑定上一页和下一页的页码,然后取消原来的超链接跳转。
核心 JS 部分
准备工作已经完成,下面的重点在数据 AJAX 请求部分。该部分逻辑分步骤实现。
第一步,给上一页和下一个按钮绑定事件
$(function()
$('.page-item').on('click',function()
page = $(this).attr('page');
// 获取数据
get_data(page);
)
)
这部分直接使用 .on()
方法进行绑定即可,注意看上述代码中的 get_data()
,该函数用于发起 AJAX 请求,获取响应,并渲染数据,代码如下。
function get_data(page)
$.ajax(
type: "get",
url: "/ss/api2",
data:
page: page
,
success: function(response)
// ajax 请求成功
render_data(response);
// 修改分页数据
$('.prev').attr('page',response["prev_page"]);
$('.next').attr('page',response["next_page"]) ;
console.log("AJAX request succeeded!");
,
error: function(error)
console.log("AJAX request failed: " + error);
);
请求的数据接口地址为 /ss/api2
,所以还需要回到 school/index.py
文件中,增加该部分函数。
@s.route('api2')
def ajax_list_school():
page = int(request.args.get("page", 1))
pagination = pagination_object(page)
return jsonify(pagination)
上述代码出现了一个新函数 jsonify()
,在 Python Flask 中,可以使用 jsonify()
函数将数据转换为 JSON 并返回给客户端。
简单的案例如下所示。
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/data')
def get_data():
data = 'key1': 'value1', 'key2': 'value2'
return jsonify(data)
if __name__ == '__main__':
app.run()
在上面的代码中,我们定义了一个视图函数 get_data()
,该函数创建了一个字典,并使用 jsonify()
函数将其转换为 JSON 并返回给客户端。
继续回到JS代码部分,在接收到数据请求之后,我们依次编写了如下代码,其分为两部分,第一部分是数据渲染,第二部分是分页组件页码变化。
render_data(response);
// 修改分页数据
$('.prev').attr('page',response["prev_page"]);
$('.next').attr('page',response["next_page"]) ;
这里主要看 render_data()
函数的实现,代码如下所示。
function render_data(response)
data_list = response["data_list"];
if(data_list.length>0)
// 清空原有数据
$('#school_list').empty();
$.each(data_list,function(index,item)
// 循环渲染数据
var row = $('<div>',
'class': 'row mt-3',
'data-custom-attribute': 'value'
);
var col =$('<div>',
'class': 'col'
);
var d_flex = $('<div>',
'class': 'd-flex'
);
d_flex.append('<div class="flex-shrink-0"><a href="#"><img class="rounded-pill img-thumbnail" width="64" height="64" src="'+item.pic+'" alt=""></a></div>');
// 生成一下标签代码
var badge = "";
$.each(item.feature.split(','),function(i,f)
badge += ' <span class="badge rounded-pill bg-primary">'+f+'</span> ';
);
d_flex.append('<div class="flex-grow-1 ms-3"><h5 class="float-start pe-3">'+item.name+'</h5><p class="ms-3">'+badge+'</p><p><em>所在省市:<span class="text-black-50">'+item.province+'--'+item.city+'</span></em></p></div>')
col.append(d_flex);
row.append(col);
$('#school_list').append(row);
)
JS代码使用了循环渲染,拼接HTML DOM 对象的方式实现,其重点代码就是在循环后台发送过来的学校对象数组,然后追加到 ID = school_list
的 DIV 中。
到此,核心代码已经编写完毕,可以进行运行测试。
但是当点击下一页时,控制台出现了如下错误。
TypeError: Object of type 'School' is not JSON serializable
该原因是由于 School
实体直接返回的是对象,不是可JSON序列化的数据,所以要继续进行修改。
找到 model.py
文件,修改 School
类文件,增加一个 to_dict()
方法。
class School(db.Model, EntityBase):
# 前面的字典注意不要丢失
def to_dict(self):
return
'name': self.name,
'province': self.province,
'city': self.city,
'feature': self.feature,
'hotValue': self.hotValue,
'pic': self.pic,
'category': self.category,
'batchTimes': self.batchTimes
然后回到 school/index.py
文件中,在 pagination_object()
函数中增加类型转换代码。
data_list = [row.to_dict() for row in data_list]
pagination["data_list"] = data_list
return pagination
重启项目,再次点击分页,即完成本案例,无刷新 AJAX 请求。
本案例到此结束,已更新到 爬虫训练场 欢迎大家访问学习。
项目同步到代码仓库 https://gitcode.net/hihell/spider_playground
📢📢📢📢📢📢
💗 你正在阅读 【梦想橡皮擦】 的博客
👍 阅读完毕,可以点点小手赞一下
🌻 发现错误,直接评论区中指正吧
📆 橡皮擦的第 813 篇原创博客
从订购之日起,案例 5 年内保证更新
以上是关于16. 你很勇哦,这么点数据就敢用异步加载?的主要内容,如果未能解决你的问题,请参考以下文章