• Flask 框架:运用Echarts绘制图形


    echarts是百度推出的一款开源的基于JavaScript的可视化图表库,该开发库目前发展非常不错,且支持各类图形的绘制可定制程度高,Echarts绘图库同样可以与Flask结合,前台使用echart绘图库进行图形的生成与展示,后台则是Flask通过render_template方法返回一串JSON数据集,前台收到后将其应用到绘图库上,实现动态展示Web服务日志状态功能。

    如下演示案例中,将分别展示运用该绘图库如何前后端交互绘制(饼状图,柱状图,折线图)这三种最基本的图形。

    实现绘制饼状图: 用于模拟统计Web容器的日志数据,通过饼状图将访问状态统计出来。

    前端部分/templates/index.html代码如下:

    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title>LyShark</title>
    		<script src="https://cdn.lyshark.com/javascript/jquery/3.5.1/jquery.min.js"></script>
    		<script src="https://cdn.lyshark.com/javascript/echarts/5.0.0/echarts.min.js"></script>
    	</head>
    
    	<body>
    		<div class="panel panel-primary" style=" 40%;height: 30%; float: left">
    		<div class="panel-heading">
    			<h3 class="panel-title">LyShark 网站访问状态统计</h3>
    		</div>
    		<div class="panel-body">
    			<div id="main" style="100%; height: 300px"></div>
    		</div>
    		</div>
    	</body>
    
    	<script type="text/javascript" charset="UTF-8">
    		var kv = new Array();
    		kv = {{ data | safe }}
    		var test = new Array();
    		for(var logkey in kv){
    			test.push( {value:kv[logkey], name:logkey} )
    		}
    		var display = function(){
    			var main = echarts.init(document.getElementById("main"));
    			var option = {
    				legend: {
    					orient: 'vertical',
    					left: 'left',
    				},
    				series: [
    					{
    						type: 'pie',
    						radius: '70%',
    						center: ['50%', '50%'],
    						detail: {formatter:'{value}'},
    						data: test
    					}
    				]
    			};
    			main.setOption(option,true);
    		};
    		display();
    	</script>
    </html>
    

    后端代码如下通过模拟render_template返回一些数据。

    from flask import Flask,render_template,request
    import json
    
    app = Flask(import_name=__name__,
                static_url_path='/python',   # 配置静态文件的访问url前缀
                static_folder='static',      # 配置静态文件的文件夹
                template_folder='templates') # 配置模板文件的文件夹
    
    def Count_Flag_And_Flow(file):
        list = []
        flag = {}
        with open(file) as f:
            contexts = f.readlines()
        for line in contexts:
            it = line.split()[8]
            list.append(it)
        list_num = set(list)
        for item in list_num:
            num = list.count(item)
            flag[item] = num
        return flag
    
    @app.route('/', methods=["GET"])
    def index():
        Address = {'226': 4, '404': 12, '200': 159, '400': 25, '102': 117, '302': 1625}
        # Address = Count_Flag_And_Flow("d://access_log")
        return render_template("index.html",data = json.dumps(Address))
    
    if __name__ == '__main__':
        app.run(host="127.0.0.1", port=80, debug=False)
    

    运行后访问自定义域名,输出如下效果的饼状图:

    实现绘制柱状图: 统计访问了本站的所有ID地址并将地址数大于2的全部显示出来.

    前端index.html代码如下

    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title>LyShark</title>
    		<script src="https://cdn.lyshark.com/javascript/jquery/3.5.1/jquery.min.js"></script>
    		<script src="https://cdn.lyshark.com/javascript/echarts/5.0.0/echarts.min.js"></script>
    	</head>
    
    	<body>
    		<div class="panel panel-primary" style=" 58%;height: 30%; float: left">
    			<div class="panel-heading">
    				<h3 class="panel-title">LyShark 网站设备类型统计</h3>
    			</div>
    			<div class="panel-body">
    				<div id="main1" style="100%; height: 300px"></div>
    			</div>
    		</div>
    	</body>
    
    	<script type="text/javascript" charset="UTF-8">
    			var kv = new Array();
    			var keys = new Array();
    			var values = new Array();
    			kv = {{ data | safe }}
    
    			for(var logkey in kv){
    				keys.push(logkey);
    				values.push(kv[logkey]);
    			}
    			var display = function() {
    				var main1 = echarts.init(document.getElementById("main1"));
    				var option = {
    					xAxis: {
    						type: 'category',
    						data: keys
    					},
    					yAxis: {
    						type: 'value'
    					},
    					series: [{
    						data: values,
    						type: 'bar'
    					}]
    				};
    				main1.setOption(option,true);
    			};
    		display();
    	</script>
    </html>
    

    后端代码如下,路由曾则只保留一个index映射

    from flask import Flask,render_template,request
    import json
    
    app = Flask(import_name=__name__,
                static_url_path='/python',   # 配置静态文件的访问url前缀
                static_folder='static',      # 配置静态文件的文件夹
                template_folder='templates') # 配置模板文件的文件夹
    
    def Count_Flag_And_Type(file):
        list = []
        flag = {}
        with open(file) as f:
            contexts = f.readlines()
        for line in contexts:
            addr = line.split()[0].replace("(","").replace(")","")
            if addr != "::1":
                list.append(addr)
    
        # 去重并将其转为字典
        list_num = set(list)
        for item in list_num:
            num = list.count(item)
            # 如果地址只有一次则忽略
            if num > 1:
                flag[item] = num
        return flag
    
    @app.route('/', methods=["GET"])
    def index():
        Types = {'Linux': 23, 'studies': 57, 'Windows': 87, 'compatible': 44, 'web': 32, 'X11': 78}
        # Types = Count_Flag_And_Type("d://access_log")
        return render_template("index.html",data = json.dumps(Types))
    
    if __name__ == '__main__':
        app.run(host="127.0.0.1", port=80, debug=False)
    

    柱状图绘制效果如下:

    实现绘制折线图: 统计指定的时间段内的访问流量数据.

    前端index.html代码如下

    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title>LyShark</title>
    		<script src="https://cdn.lyshark.com/javascript/jquery/3.5.1/jquery.min.js"></script>
    		<script src="https://cdn.lyshark.com/javascript/echarts/5.0.0/echarts.min.js"></script>
    	</head>
    
    	<body>
    		<div class="panel panel-primary" style=" 100%;height: 30%; float: left">
    			<div class="panel-heading">
    				<h3 class="panel-title">LyShark 网站流量统计</h3>
    			</div>
    			<div class="panel-body">
    				<div id="main" style="100%; height: 400px"></div>
    			</div>
    		</div>
    	</body>
    
    	<script type="text/javascript" charset="UTF-8">
    			var kv = new Array();
    			var keys = new Array();
    			var values = new Array();
    			kv = {{ data | safe }};
    			for(var logkey in kv){
    				keys.push(logkey);
    				values.push(kv[logkey]);
    			}
    
    			var display = function() {
    				var main = echarts.init(document.getElementById("main"));
    				var option = {
    					xAxis: {
    						type: 'category',
    						boundaryGap: false,
    						data: keys
    					},
    					yAxis: {
    						type: 'value'
    					},
    					series: [{
    						data: values,
    						type: 'line',
    						areaStyle: {},
    					}]
    				};
    				main.setOption(option,true);
    			};
    		display();
    	</script>
    </html>
    

    后端代码如下,路由曾则只保留一个index映射

    from flask import Flask,render_template,request
    import json
    
    app = Flask(import_name=__name__,
                static_url_path='/python',   # 配置静态文件的访问url前缀
                static_folder='static',      # 配置静态文件的文件夹
                template_folder='templates') # 配置模板文件的文件夹
    
    def Count_Time_And_Flow(file):
        times = {}  # key 保存当前时间信息
        flow = {}   # value 当前时间流量总和
        Count= 0    # 针对IP地址的计数器
        with open(file) as f:
            contexts = f.readlines()
        for line in contexts:
            if line.split()[9] != "-" and line.split()[9] != '"-"':
                size = line.split()[9]
            temp = line.split()[3]
            ip_attr = temp.split(":")[1] + ":" + temp.split(":")[2]
            Count = int(size) + Count
            if ip_attr in times.keys():
                flow[ip_attr] = flow[ip_attr] + int(size)
            else:
                times[ip_attr] = 1
                flow[ip_attr] = int(size)
        return flow
    
    @app.route('/', methods=["GET"])
    def index():
        OutFlow = {'03:30': 12, '03:48': 25, '04:15': 47, '04:28': 89, '04:42': 66, '04:51': 54}
        # OutFlow = Count_Time_And_Flow("d://access_log")
        return render_template("index.html",data = json.dumps(OutFlow))
    
    if __name__ == '__main__':
        app.run(host="127.0.0.1", port=80, debug=False)
    

    折现图绘制效果如下:

    如上是三种常用图形的绘制方式,其他图形同理可以参考如上方代码中的写法,我们可以将这三个图形合并在一起,主要是前端对其进行排版即可。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="https://cdn.lyshark.com/javascript/bootstrap/3.3.7/css/bootstrap.min.css">
        <script type="text/javascript" src="https://cdn.lyshark.com/javascript/jquery/3.5.1/jquery.min.js"></script>
        <script type="text/javascript" src="https://cdn.lyshark.com/javascript/echarts/5.0.0/echarts.min.js"></script>
    </head>
    <body>
    
        <!--饼状图绘制方法-->
        <div class="panel panel-primary" style=" 40%;height: 30%;float: left">
            <div class="panel-heading">
                <h3 class="panel-title">饼状图绘制</h3>
            </div>
            <div class="panel-body">
                <div id="PieChart" style="100%; height: 300px"></div>
            </div>
        </div>
    
        <!--柱状图绘制方法-->
        <div class="panel panel-primary" style=" 58%;height: 30%; float: right">
            <div class="panel-heading">
                <h3 class="panel-title">柱状图绘制</h3>
            </div>
            <div class="panel-body">
                <div id="HistogramChart" style="100%; height: 300px"></div>
            </div>
        </div>
    
        <!--折线图绘制方法-->
        <div class="panel panel-primary" style=" 100%;height: 40%; float: left">
            <div class="panel-heading">
                <h3 class="panel-title">折线图绘制</h3>
            </div>
            <div class="panel-body">
                <div id="Linechart" style="100%; height: 460px"></div>
            </div>
        </div>
    
        <!--饼状图绘制方法-->
        <script type="text/javascript" charset="UTF-8">
            var kv = new Array();
            kv = {{ Address | safe }}
            var test = new Array();
            for(var logkey in kv){
                test.push( {value:kv[logkey], name:logkey} )
            }
            var display = function(){
                var echo = echarts.init(document.getElementById("PieChart"));
                var option = {
                    legend: {
                        orient: 'vertical',
                        left: 'left',
                    },
                    series: [
                        {
                            type: 'pie',
                            radius: '70%',
                            center: ['50%', '50%'],
                            detail: {formatter:'{value}'},
                            data: test
                        }
                    ]
                };
                echo.setOption(option,true);
            };
            display();
        </script>
    
        <!--柱状图绘制方法-->
        <script type="text/javascript" charset="UTF-8">
            var kv = new Array();
            var keys = new Array();
            var values = new Array();
            kv = {{ Types | safe }}
    
            for(var logkey in kv){
                keys.push(logkey);
                values.push(kv[logkey]);
            }
            var display = function() {
                var echo = echarts.init(document.getElementById("HistogramChart"));
                var option = {
                    tooltip: {
                        trigger: 'axis',
                        axisPointer: {
                          type: 'shadow'
                        }
                    },
                    grid: {
                        left: '3%',
                        right: '4%',
                        bottom: '3%',
                        containLabel: true
                    },
                    xAxis: {
                        type: 'category',
                        data: keys
                    },
                    yAxis: {
                        type: 'value'
                    },
                    series: [{
                        data: values,
                        type: 'bar'
                    }]
                };
                echo.setOption(option,true);
            };
            display();
        </script>
    
        <!--折线图绘制方法-->
        <script type="text/javascript" charset="UTF-8">
    
            // 函数主要用于将传入的字典分解成key,value格式并返回
            var get_key_value = function(kv)
            {
                var keys = new Array();
                var values = new Array();
    
                for(var logkey in kv)
                {
                    keys.push(logkey);
                    values.push(kv[logkey]);
                }
                return [keys,values];
            }
    
            // 输出1分钟负载
            var kv = new Array();
            kv = {{ x | safe }};
            var x = get_key_value(kv);
    
            // 输出5分钟负载
            var kv = new Array();
            kv = {{ y | safe }};
            var y = get_key_value(kv);
    
            // 输出15分钟负载
            var kv = new Array();
            kv = {{ z | safe }};
            var z = get_key_value(kv);
    
            // 显示利用率
            var display = function() {
                var echo = echarts.init(document.getElementById("Linechart"));
                var option = {
                    title: {
                        left: 'left',
                        text: 'CPU 利用表',
                    },
                    // 调节大小
                    grid: {
                        left: '3%',
                        right: '4%',
                        bottom: '3%',
                        containLabel: true
                    },
                    // tooltip 鼠标放上去之后会自动出现坐标
                    tooltip: {
                        trigger: 'axis',
                        axisPointer: {
                            type: 'cross',
                            label: {
                                backgroundColor: '#6a7985'
                            }
                        }
                    },
                legend: {
                    data: ['1分钟负载', '5分钟负载', '15分钟负载']
                },
    
                xAxis: {
                    type: 'category',
                    // data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
                    data: x[0]
                },
                yAxis: {
                    type: 'value'
                },
                series:
                [
                    {
                        name: "1分钟负载",
                        stack: "总量",
                        //data: [10, 25, 99, 87, 54, 66, 2],
                        data: x[1],
                        type: 'line'
                    },
                    {
                        name: "5分钟负载",
                        stack: "总量",
                        //data: [89, 57, 85, 44, 25, 4, 54],
                        data: y[1],
                        type: 'line'
                    },
                    {
                        name: "15分钟负载",
                        stack: "总量",
                        //data: [1, 43, 2, 12, 5, 4, 7],
                        data: z[1],
                        type: 'line'
                    }
                ]
                };
                echo.setOption(option,true);
            };
            display();
        </script>
    </body>
    

    后端代码如下,其中的参数可以从数据库内提取也可以从文件中读入。

    from flask import Flask,render_template,request
    import json
    
    app = Flask(import_name=__name__,
                static_url_path='/python',   # 配置静态文件的访问url前缀
                static_folder='static',      # 配置静态文件的文件夹
                template_folder='templates') # 配置模板文件的文件夹
    
    @app.route('/', methods=["GET"])
    def index():
        Address = {'226': 4, '404': 12, '200': 159, '400': 25, '102': 117, '302': 1625}
        Types = {'Linux': 23, 'studies': 57, 'Windows': 87, 'compatible': 44, 'web': 32, 'X11': 78}
        x = {'03:30': 12, '03:48': 25, '04:15': 47, '04:28': 89, '04:42': 66, '04:51': 54}
        y = {'05:22': 55, '07:48': 29, '07:15': 98, '08:54': 11, '08:41': 61, '06:51': 5}
        z = {'07:30': 1, '09:48': 5, '06:15': 24, '08:28': 59, '2:42': 11, '08:51': 22}
        
        return render_template("index.html",Address = json.dumps(Address), Types= json.dumps(Types), x = json.dumps(x), y = json.dumps(y), z = json.dumps(z))
    
    if __name__ == '__main__':
        app.run(host="127.0.0.1", port=80, debug=False)
    

    输出效果如下:

  • 相关阅读:
    解析大型.NET ERP系统 权限模块设计与实现
    Enterprise Solution 开源项目资源汇总 Visual Studio Online 源代码托管 企业管理软件开发框架
    解析大型.NET ERP系统 单据编码功能实现
    解析大型.NET ERP系统 单据标准(新增,修改,删除,复制,打印)功能程序设计
    Windows 10 部署Enterprise Solution 5.5
    解析大型.NET ERP系统 设计异常处理模块
    解析大型.NET ERP系统 业务逻辑设计与实现
    解析大型.NET ERP系统 多国语言实现
    Enterprise Solution 管理软件开发框架流程实战
    解析大型.NET ERP系统 数据审计功能
  • 原文地址:https://www.cnblogs.com/LyShark/p/16755896.html
Copyright © 2020-2023  润新知