Python+Flask+Mysql+Echarts实现前后端交互及数据可视化

发布于 2023年12月20日

记录一下从DevOps中取数据存入Mysql并进行图表展示。已经有一份代码是可以从DevOps中获取到Bug数据,并存入xls文件中。如下图所示,前面是项目名称后面是日期格式。接下来要做的是使用python脚本将文件里的内容存入Mysql中并使用Flask配合Echarts进行展示。
图片1-vdqi.png
文件内容:
图片2-nzbn.png
里面有七个字段,所以就要在mysql中创建七个字段并将数据存入其中,为了避免重复导入,可以给BugId字段设置唯一索引。

一、安装Mysql

1、下载Mysql镜像

docker pull mysql:5.7.40

2、创建目录

首先在linux主机中创建mysql的挂载目录

mkdir -p mysql/conf
mkdir mysql/data
mkdir mysql/log

3、添加mysql的配置文件,设置编码为utf8格式。

vim conf/my.cnf

# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
​
[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
​
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
​
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
character_set_server=utf8
init_connect='SET NAMES utf8

4、启动mysql

docker run -d --name mysql -it  --restart=always \
-v /app/data/mysql/data:/var/lib/mysql \
-v /app/data/mysql/conf/my.cnf:/etc/my.cnf \
-v /app/data/mysql/log:/var/log/mysql \
-p 3306:3306 -e MYSQL_ROOT_PASSWORD="admin1234" \
-e TZ=Asia/Shanghai \
mysql:5.7.40 --lower_case_table_names=1 --character-set-server=utf8 --collation-server=utf8_general_ci

5、如果需要手动连接的话,首先先进入容器内,然后再连接。

docker exec -it mysql bash
​
mysql -uroot -padmin1234
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.40 MySQL Community Server (GPL)
​
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
​
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
​
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
​
mysql>

6、Navicat查看Mysql

点击左上角连接,选择Mysql,然后输入名称与ip地址、用户名、密码连接即可。
图片3-rskx.png
创建连接成功后,直接点击就可以看到数据库与表
图片4-ulzc.png

二、Python连接Mysql

这边使用的是VScode。安装pymysql模块就可以使用连接mysql,要确保可以通mysql的那台服务器

1、安装Python3.6

Windows 64位
https://www.python.org/ftp/python/3.6.3/python-3.6.3-amd64.exe
然后,运行下载的 EXE 安装包:
图片5-nmpv.png
点 “Install Now” 即可完成安装
图片6-nkse.png
图片7-uwxn.png
图片8-ajhh.png
安装完成后打开VScode,安装python插件,在终端中查看python版本
图片9-fqaw.png

2、安装模块

直接使用pip install +模块名称就可以下载,如果下载比较慢,可以选择国内的源
pip install 模块名称 -i https://pypi.tuna.tsinghua.edu.cn/simple
我们需要用到flask模块、xlwt模块、bs4模块、azure.devops模块,需要其他的自行下载就行。
图片10-youf.png

3、连接mysql将文件内容存入数据库中

代码如下:
代码的意思是连接Mysql数据库,并创建python_mce数据库,进入数据库中创建bugs表,在表中创建七个字段并给BugId创建唯一索引。打开文件读取文件内容,将内容写入表内。

import xlrd
import pymysql
import time
import sys
import os
import xlwt
class getBugs:
    def Insert_MySQL(self, projectdir):
        conn = pymysql.connect(host='10.0.0.10',
                               user='root',
                               password='admin1234',
                               )
        # 创建游标对象
        cur = conn.cursor()
        try:
            # 建python_mce库
            cur.execute("create database python_mce character set utf8;")
        except:
            print('此数据库已存在')
        # 进入python_mce数据库
        cur.execute("use python_mce ")
        try:
            # 创建表格设置字段属性
            cur.execute("CREATE TABLE bugs (BugId varchar(255)," \
                        "Title varchar(255),State varchar(255),AssignedTo varchar(255)," \
                        "Priority varchar(255),Terminal_Module varchar(255),FixedVersion varchar(520))")
        except:
            print('此表名已存在')
            conn.rollback()  # 失败则回滚
        try:
            cur.execute("alter table bugs add unique key `bugs_index`(`BugId`)")
        except:
            print('已为BugId添加唯一索引')
        # 给表添加内容的sql语句
        sql = "insert into bugs(BugId,Title,State,AssignedTo," \
              "Priority,Terminal_Module,FixedVersion) values (%s, %s, %s, %s, %s, %s, %s)"
        # 打开文件
        book = xlrd.open_workbook(projectdir)
        # 表名称
        sheet = book.sheet_by_name("bugs")
        # 读取文件内容并执行sql语句写入mysql
        i = sheet.nrows
        for r in range(1, sheet.nrows):
            BugId = sheet.cell(r, 0).value
            Title = sheet.cell(r, 1).value
            State = sheet.cell(r, 2).value
            AssignedTo = sheet.cell(r, 3).value
            Priority = sheet.cell(r, 4).value
            Terminal_Module = sheet.cell(r, 5).value
            FixedVersion = sheet.cell(r, 6).value
            try:
                cur.execute(sql, (BugId, Title, State, AssignedTo, Priority, Terminal_Module, FixedVersion))
            except:
                print("此数据已经添加完成,无需添加")
            conn.commit()
        # 关闭连接
        cur.close()
        conn.close()
if __name__ == '__main__':
    up = getBugs()
    workbookdir = ('./BugResolvedVersion/' + projectName + '-' + time.strftime('%Y%m%d_%H%M%S', time.localtime()) + '.xls')
    workbook.save(workbookdir)
    projectdir = workbookdir
    up.Insert_MySQL(projectdir)

三、Flask+Echarts可视化

1、读取Mysql数据

写一个Mysql的python脚本用来读取数据,代码如下:
文件名称:Mysql.py

import pymysql
class Mysql(object):
    def __init__(self):
        try:
            self.conn = pymysql.connect(host='10.0.0.10',user='root',password='admin1234',database='python_mce',charset="utf8")
            self.cursor = self.conn.cursor()    # 用来获得python执行Mysql命令的方法(游标操作)
            print("连接数据库成功")
        except:
            print("连接失败")
​
    def getItems(self):
        self.cursor.execute('use python_mce')
​
        sql= "select Terminal_Module,count(*) as count from bugs group by Terminal_Module having count>0;"#获取bugs表内Terminal_Module字段的数据,并将重复的统计出来,显示有多少个。
        self.cursor.execute(sql)
        items = self.cursor.fetchall()  #接收全部的返回结果行
        return items

2、Flask+Echarts数据展示

将上面Mysql.py和Flask.py放到同一目录下,也可以写入一个文件中,都可以。
这样就可以调用mysql的数据。
目录结构:
图片11-hcfv.png
只需要创建static目录和templates目录,并在其中放入echarts.js文件和index.html文件即可。
https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js下载echarts.js文件
文件名称:Flask.py
启动文件后在127.0.0.1:5000端口访问。

# coding:utf-8
from flask import Flask
from flask import render_template
from Mysql import Mysql
import json
app = Flask(__name__)
def echarts_pie(list):
    datavar = []
    for name, value in list:
        datavar.append({'value': value, 'name': name})
    return json.dumps({
        'title': {
            'text': 'BUG统计图',
            'left': 'center'
        },
        'tooltip': {
            'trigger': 'item'
        },
        'legend': {
            'orient': 'vertical',
            'left': 'left'
        },
        'series': [
            {
                'name': 'Bug数量',
                'type': 'pie',
                'radius': '50%',
                'data': datavar,
                'emphasis': {
                    'itemStyle': {
                        'shadowBlur': 10,
                        'shadowOffsetX': 0,
                        'shadowColor': 'rgba(0, 0, 0, 0.5)'
                    }
                }
            }
        ]
    })
app.add_template_filter(echarts_pie, "pie")
​
def echarts_bar(list):
    db = Mysql()
    it = db.getItems()
    data = []
    value = []
    for i in it:
        data.append(i[0])
        value.append(i[1])
    return json.dumps({
        'title': {
            'text': 'BUG数量'
        },
        'dataZoom': [{
            'type': 'slider',
            'show': True,
            'xAxisIndex': [0],
            'left': '9%',
            'bottom': -5,
            'start': 10,
            'end': 20
        }],
        'xAxis': {
            'name': "BUG名称",
            'type': 'category',
            'data': data,
        },
        'yAxis': {
            'name': "数量",
            'type': 'value',
            'axisLabel': {
                'formatter': '{value} 个'}
        },
        'series': [
            {
                'type': 'bar',
                'data': value,
                'itemStyle': {'normal': {'color': "#31b0d5"}}
            }
        ]
    })
app.add_template_filter(echarts_bar, "bar")
​
@app.route("/")
def index():
    db = Mysql()
    it = db.getItems()
    return render_template("index.html", bardata=it, piedata=it)
​
if __name__ == "__main__":
    from gevent import pywsgi
    server = pywsgi.WSGIServer(('127.0.0.1',5000),app)
    server.serve_forever()

文件名称:index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>统计图</title>
    <script src="/static/echarts.js"></script>
    <style>
        .chart {
            width: 100%;
            height: 600px;
        }
    </style>
</head>
<body>
<div id="main-pie" class="chart"></div>
<div id="main-bar" class="chart"></div>
    <script type="text/javascript">
        var pieChart = echarts.init(document.getElementById('main-pie'), 'dark');
        pieChart.setOption({{ piedata|pie|safe }});
        var barChart = echarts.init(document.getElementById('main-bar'), 'dark');
        barChart.setOption({{ bardata|bar|safe }});
     </script>
</body>
</html>

3、启动Flask.py文件

打开终端进入Bug图表
python Flask.py
图片12-jgbl.png
在浏览器http://127.0.0.1:5000/访问
图片13-umtb.png
图片14-xipm.png