Flask前后端数据动态交互涉及用户界面与服务器之间的灵活数据传递。用户界面使用ECharts图形库实时渲染数据。它提供了丰富多彩、交互性强的图表和地图,能够在网页上直观、生动地展示数据。ECharts支持各种常见的图表类型,包括折线图、柱状图、饼图、散点图等,同时还支持动画效果、数据筛选、区域缩放等交互功能。
Flask后端通过render_template方法将查询得到的JSON数据传递至前端,使得用户能够查询特定时间段内的数据。这种交互方式实现了动态图形展示,为用户提供了更直观、实时的数据体验。通过此系统,用户可通过前端界面直接选择时间范围,后台服务器相应地返回相应的数据,实现了数据的动态交互与图形化展示。
JQuery绑定事件 jQuery 是一个快速、轻量级、跨浏览器的JavaScript库。它旨在简化HTML文档遍历、事件处理、动画操作和AJAX等常见任务,使开发者能够更方便地处理DOM操作和前端交互。
以下这段HTML代码实现了一个包含表单的页面,用户可以输入主机地址、开始时间、结束时间以及选择负载类型,然后通过点击按钮进行数据查询。
代码首先通过Ajax接口实现了参数传递,使用了jQuery中的click
方法绑定了按钮点击事件。概述如下:
表单提交和Ajax请求:
在用户填写完表单后,通过jQuery的click
方法,给按钮绑定了一个点击事件。
在点击事件中,使用$.ajax
函数实现了异步的数据请求。
通过$("#myForm").serialize()
将表单数据序列化,然后作为请求参数发送给后端。
后端响应:
请求的目标URL是根目录(“/“),这可能是Flask或其他后端框架的路由。
后端处理接收到的数据,执行相应的逻辑,并返回一个JSON格式的数据。
前端处理响应数据:
当Ajax请求成功时,触发了success
回调函数。
在回调函数中,使用JSON.parse(data)
解析后端返回的JSON字符串,得到一个包含时间、X、Y、Z数据的字典(ref_dict
)。
数据展示:
解析后的数据传递给create_graphical
函数。
create_graphical
函数负责处理这些数据,这里是打印到控制台。
这种结构使得用户在填写表单并点击按钮后,能够通过Ajax请求将数据发送给后端,并在后端执行相应逻辑后返回JSON格式的数据。前端接收到数据后进行解析处理,这里简单打印到控制台,实际应用中可以进一步用于图表的动态更新等操作。这样实现了前后端之间的动态数据传递和交互。如下index.html
代码如下所示;
<!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <script type ="text/javascript" src ="https://www.lyshark.com/javascript/jquery/3.5.1/jquery.min.js" > </script > </head > <body > <form action ="/" method ="post" id ="myForm" > <p > 主机地址: <input type ="text" name ="address" placeholder ="输入主机IP地址" > </p > <p > 开始时间: <input type ="datetime-local" name ="start_datetime" /> </p > <p > 结束时间: <input type ="datetime-local" name ="end_datetime" /> </p > <select name ="select" > <option value ="load5" > 五分钟负载</option > <option value ="load10" > 十分钟负载</option > <option value ="load15" > 十五分钟负载</option > <option value ="load_all" > 全部输出</option > </select > <input name ="btn" id ="btn" type ="button" value ="查询数据" /> </form > <script type ="text/javascript" charset ="UTF-8" > var create_graphical = function (time,x,y,z ) { console .log ("日期: " + time); console .log ("X: " + x); console .log ("Y: " + y); console .log ("Z: " + z); } </script > <script type ="text/javascript" > $("#btn" ).click (function ( ) { $.ajax ({ url : "/" , type : "POST" , data : $("#myForm" ).serialize (), success :function (data ) { var ref_dict = JSON .parse (data); create_graphical (ref_dict.time , ref_dict.x , ref_dict.y , ref_dict.z ) } }) }) </script > </body >
后台app.py
则通过request.form.get
方法接收用户数据,并将收到的数据打印到后台,将数据拼接组合成一个JSON数组并使用json.dumps()
将数据返回给前端;
from flask import Flask,render_template,requestimport jsonapp = Flask(__name__) @app.route('/' ,methods=['POST' ,'GET' ] ) def index (): if request.method == "GET" : return render_template("index.html" ) elif request.method == "POST" : address = request.form.get("address" ) start_datetime = request.form.get("start_datetime" ) end_datetime = request.form.get("end_datetime" ) select_value = request.form.get("select" ) print (address,start_datetime,end_datetime,select_value) ref_time = ["11:12" ,"11:13" ,"11:14" ,"11:15" ,"11:16" ] ref_x = [4 ,5 ,8 ,9 ,4 ] ref_y = [6 ,7 ,8 ,9 ,0 ] ref_z = [4 ,3 ,2 ,4 ,6 ] ref_dict = {"time" :ref_time, "x" : ref_x, "y" : ref_y, "z" : ref_z} return json.dumps(ref_dict, ensure_ascii=False ) if __name__ == '__main__' : app.run()
运行代码,通过填入不同的参数传入后台,前台则可以看到后台回传参数,如下图所示;
生成测试数据 如下提供的这段代码的主要功能是定期获取主机的CPU负载数据,将数据插入SQLite数据库中。这种实时数据采集的方式可用于监控系统性能,尤其是在Web应用中,可以用于实时更新图表或报告系统的负载情况,运行这段程序并等待5分钟的数据采集。
以下是对该代码的概述:
数据库创建函数 (CreateDB
):
连接到SQLite数据库(database.db
)。
创建了一个名为 CpuLoadDB
的表,包含主机地址 (address
)、时间 (times
)、5分钟负载 (load5
)、10分钟负载 (load10
)、15分钟负载 (load15
) 的字段。
获取CPU负载函数 (GetCPU
):
获取当前时间并格式化为字符串。
使用 psutil.cpu_percent
获取实时CPU负载,返回一个包含主机地址、时间、5分钟负载、10分钟负载、15分钟负载的字典。
主程序 (__main__
):
调用 CreateDB
函数创建数据库表。
进入一个无限循环,每次循环中获取CPU负载数据,构建插入语句,并将数据插入数据库中。
在控制台打印插入语句,便于调试。
通过 time.sleep(1)
控制每秒执行一次,模拟实时数据更新。
import sqlite3import time,psutil,datetimedef CreateDB (): conn = sqlite3.connect("database.db" ) cursor = conn.cursor() create = "create table CpuLoadDB(" \ "address char(32) not null," \ "times char(32) not null," \ "load5 char(32) not null," \ "load10 char(32) not null," \ "load15 char(32) not null" \ ")" cursor.execute(create) conn.commit() cursor.close() conn.close() def GetCPU (addr ): times = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M" ) cpu = psutil.cpu_percent(interval=None ,percpu=True ) dict = {'address' : addr,'times' : times,'load5' : cpu[0 ],'load10' : cpu[1 ],'load15' :cpu[2 ]} return dict if __name__ == "__main__" : CreateDB() conn = sqlite3.connect("database.db" ) cursor = conn.cursor() while True : dict = GetCPU("127.0.0.1" ) insert = 'insert into CpuLoadDB(address,times,load5,load10,load15) values("{}","{}","{}","{}","{}")' .\ format (dict ["address" ],dict ["times" ],dict ["load5" ],dict ["load10" ],dict ["load15" ]) print (insert) cursor.execute(insert) conn.commit() time.sleep(1 )
运行上述程序,开始时间2023-11-27 15:17
结束于2023-11-27 15:36
,采集到的数据如下图所示;
实现历史查询 通过简洁而功能强大的前端页面,用户可以选择主机、设定时间范围,并实时查看CPU负载的变化。后端使用Flask框架搭建,借助psutil库获取实时CPU负载数据,并将数据存储在SQLite数据库中。前端使用jQuery和ECharts库,通过Ajax请求实现与后端的动态数据交互,并在页面上实时绘制CPU负载的折线图。
数据生后后,我们在原来代码基础之上增加echarts.js
绘图库代码,用户在前台填写表格并发送给后端,当后端处理后输出给前端JSON格式,前端获取到该格式之后自动再将其绘制出来,代码如下所示;
<!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <script type ="text/javascript" src ="https://www.lyshark.com/javascript/jquery/3.5.1/jquery.min.js" > </script > <script type ="text/javascript" src ="https://www.lyshark.com/javascript/echarts/5.3.0/echarts.min.js" > </script > </head > <body > <form action ="/" method ="post" id ="myForm" > <p > 选择主机: <select name ="address" style ="width: 185px; height: 25px" > {% for item in addr %} <option value ="{{ item }}" > {{ item }}</option > {% endfor %} </select > </p > <p > 开始时间: <input type ="datetime-local" name ="start_datetime" /> </p > <p > 结束时间: <input type ="datetime-local" name ="end_datetime" /> </p > <p > 选择图形: <select name ="select" style ="width: 185px; height: 25px" > <option value ="load5" > 五分钟负载</option > <option value ="load10" > 十分钟负载</option > <option value ="load15" > 十五分钟负载</option > </select > </p > <input name ="btn" id ="btn" type ="button" value ="查询数据" /> </form > <div id ="main" style ="width: 100%;height:450px;border:1px solid #dddddd;float: left;margin-top: 10px;" > </div > <script type ="text/javascript" charset ="UTF-8" > var create_graphical = function (time,cpu ) { var myChart_cpu = echarts.init (document .getElementById ('main' )); myChart_cpu.setOption ({ tooltip : {}, animation : false , xAxis : { data : [] }, grid : { left : '3%' , right : '4%' , top :'3%' , bottom : '3%' , containLabel : true }, tooltip : { trigger : 'axis' , axisPointer : { type : 'cross' , label : { backgroundColor : '#6a7985' } } }, yAxis : {}, series : [{ type : 'line' , data : [] }] }); myChart_cpu.setOption ({ xAxis : { data : time }, series : [{ name : 'CPU负载率' , data : cpu }] }); }; </script > <script type ="text/javascript" > $("#btn" ).click (function ( ) { $.ajax ({ url : "/" , type : "POST" , dataType : "text" , data : $("#myForm" ).serialize (), success :function (data ) { var ref_dict = JSON .parse (data); create_graphical (ref_dict.time , ref_dict.cpu ) } }) }) </script > </body >
后端首先判断请求来源,如果是GET方式请求,则先查询数据库中有哪些IP地址,并对这些地址去重后返回给前端的select
组件,而如果是POST请求,则根据条件匹配记录,并将匹配结果返回给前台即可,后端代码如下所示;
from flask import Flask,render_template,requestimport jsonimport sqlite3app = Flask(__name__) @app.route('/' ,methods=['POST' ,'GET' ] ) def index (): if request.method == "GET" : address_set = set () conn = sqlite3.connect("database.db" ) cursor = conn.cursor() for address_count in cursor.execute("select address from CpuLoadDB;" ).fetchall(): address_set.add(address_count[0 ]) return render_template("index.html" ,addr = list (address_set)) elif request.method == "POST" : address = request.form.get("address" ) start_datetime = request.form.get("start_datetime" ) end_datetime = request.form.get("end_datetime" ) select_value = request.form.get("select" ) time_ref = [] cpu_load_ref = [] conn = sqlite3.connect("database.db" ) cursor = conn.cursor() select = "select * from CpuLoadDB where address=='{}' and times >='{}' and times <='{}'" .\ format (address,start_datetime,end_datetime) if select_value == "load5" : for ref in cursor.execute(select).fetchall(): time_ref.append(ref[1 ].split("T" )[1 ]) cpu_load_ref.append(float (ref[2 ])) ref_dict = {"time" :time_ref, "cpu" : cpu_load_ref} return json.dumps(ref_dict, ensure_ascii=False ) if select_value == "load10" : for ref in cursor.execute(select).fetchall(): time_ref.append(ref[1 ].split("T" )[1 ]) cpu_load_ref.append(float (ref[3 ])) ref_dict = {"time" :time_ref, "cpu" : cpu_load_ref} return json.dumps(ref_dict, ensure_ascii=False ) if select_value == "load15" : for ref in cursor.execute(select).fetchall(): time_ref.append(ref[1 ].split("T" )[1 ]) cpu_load_ref.append(float (ref[4 ])) ref_dict = {"time" : time_ref, "cpu" : cpu_load_ref} return json.dumps(ref_dict, ensure_ascii=False ) if __name__ == '__main__' : app.run()
代码被运行后,会首次使用GET方式获取主机列表及负载单选框列表,此处我们查询开始时间2023-11-27 15:20
结束于2023-11-27 15:30
,这10分钟的数据,采集到的数据如下图所示;