Web开发Python实现Web图表功能(pyecharts,Flask)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Web开发Python实现Web图表功能(pyecharts,Flask)相关的知识,希望对你有一定的参考价值。

<font color=purple face=华文行楷 size="5">"柳丝榆荚自芳菲,不管桃飘与李飞;"

1、简介

2、Flask + pyecharts

2.1 Flask 模板渲染

$ mkdir pyecharts-flask-demo
$ cd pyecharts-flask-demo
$ mkdir templates

将 pyecharts 模板,位于 pyecharts.render.templates 拷贝至刚新建的 templates 文件夹。

  • server.py
from flask import Flask
from jinja2 import Environment, FileSystemLoader
from pyecharts.globals import CurrentConfig
from markupsafe import Markup

# 关于 CurrentConfig,可参考 [基本使用-全局变量]
CurrentConfig.GLOBAL_ENV = Environment(loader=FileSystemLoader("./templates"))

from pyecharts import options as opts
from pyecharts.charts import Bar


app = Flask(__name__, static_folder="templates")


def bar_base() -> Bar:
    c = (
        Bar()
        .add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"])
        .add_yaxis("商家A", [5, 20, 36, 10, 75, 90])
        .add_yaxis("商家B", [15, 25, 16, 55, 48, 8])
        .set_global_opts(title_opts=opts.TitleOpts(title="Bar-基本示例", subtitle="爱看书的小沐"))
    )
    return c

@app.route("/")
def index():
    c = bar_base()
    return Markup(c.render_embed())

if __name__ == "__main__":
    app.run()

2.2 Flask 前后端分离

新建一个 html 文件。 新建 HTML 文件保存位于项目根目录的 templates 文件夹,这里以如下 index.html 为例. 主要用到了 jquery 和 pyecharts 管理的 echarts.min.js 依赖。

  • index.html:
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>动态更新数据</title>
    <script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
    <script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>
</head>
<body>
    <div id="bar" style="width:1000px; height:600px;"></div>
    <script>
      (
        function () 
            var result_json =  result_json|tojson ;
            // var result = JSON.parse(result_json);
            var chart = echarts.init(document.getElementById(bar), gray, renderer: canvas);
            $.ajax(
                type: "GET",
                url: "http://127.0.0.1:5000/barChart",
                dataType: json,
                data: result: result_json,
                success: function (result) 
                    chart.setOption(result);
                
            );
        
    )
    </script>
</body>
</html>
  • app.py:
from random import randrange
from flask import Flask, render_template
from pyecharts import options as opts
from pyecharts.charts import Bar

app = Flask(__name__, static_folder="templates")

def bar_base() -> Bar:
    c = (
        Bar()
        .add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"])
        .add_yaxis("商家A", [randrange(0, 100) for _ in range(6)])
        .add_yaxis("商家B", [randrange(0, 100) for _ in range(6)])
        .set_global_opts(title_opts=opts.TitleOpts(title="Bar-基本示例", subtitle="我是副标题"))
    )
    return c


@app.route("/")
def index():
    return render_template("index.html")


@app.route("/barChart")
def get_bar_chart():
    c = bar_base()
    return c.dump_options_with_quotes()


if __name__ == "__main__":
    app.run()

2.3 定时全量更新图表

前端主动向后端进行数据刷新 定时刷新的核心在于 HTML 的 setInterval 方法。

  • index.html:
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Awesome-pyecharts</title>
    <script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
    <script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>

</head>
<body>
    <div id="bar" style="width:1000px; height:600px;"></div>
    <script>
        var chart = echarts.init(document.getElementById(bar), white, renderer: canvas);

        $(
            function () 
                fetchData(chart);
                setInterval(fetchData, 2000);
            
        );

        function fetchData() 
            $.ajax(
                type: "GET",
                url: "http://127.0.0.1:5000/barChart",
                dataType: json,
                success: function (result) 
                    chart.setOption(result);
                
            );
        
    </script>
</body>
</html>
  • app.py: 代码同上。

2.4 定时增量更新图表

  • index.html:
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Awesome-pyecharts</title>
    <script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
    <script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>

</head>
<body>
    <div id="bar" style="width:1000px; height:600px;"></div>
    <script>
        var chart = echarts.init(document.getElementById(bar), white, renderer: canvas);
        var old_data = [];
        $(
            function () 
                fetchData(chart);
                setInterval(getDynamicData, 2000);
            
        );

        function fetchData() 
            $.ajax(
                type: "GET",
                url: "http://127.0.0.1:5000/lineChart",
                dataType: "json",
                success: function (result) 
                    chart.setOption(result);
                    old_data = chart.getOption().series[0].data;
                
            );
        

        function getDynamicData() 
            $.ajax(
                type: "GET",
                url: "http://127.0.0.1:5000/lineDynamicData",
                dataType: "json",
                success: function (result) 
                    old_data.push([result.name, result.value]);
                    chart.setOption(
                        series: [data: old_data]
                    );
                
            );
        

    </script>
</body>
</html>
  • app.py:
from random import randrange

from flask.json import jsonify
from flask import Flask, render_template

from pyecharts import options as opts
from pyecharts.charts import Line


app = Flask(__name__, static_folder="templates")


def line_base() -> Line:
    line = (
        Line()
        .add_xaxis(["".format(i) for i in range(10)])
        .add_yaxis(
            series_name="",
            y_axis=[randrange(50, 80) for _ in range(10)],
            is_smooth=True,
            label_opts=opts.LabelOpts(is_show=False),
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(title="动态数据"),
            xaxis_opts=opts.AxisOpts(type_="value"),
            yaxis_opts=opts.AxisOpts(type_="value"),
        )
    )
    return line


@app.route("/")
def index():
    return render_template("index.html")


@app.route("/lineChart")
def get_line_chart():
    c = line_base()
    return c.dump_options_with_quotes()

idx = 9

@app.route("/lineDynamicData")
def update_line_data():
    global idx
    idx = idx + 1
    return jsonify("name": idx, "value": randrange(50, 80))

if __name__ == "__main__":
    app.run()

3、Flask + echarts.js

3.1 直接渲染

  • app.py:
from flask import Flask, render_template

app = Flask(__name__)

@app.route(/)
def index():
    return render_template(index.html)

if __name__ == __main__:
    app.run(debug=True)
  • index.html:
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>第一个 ECharts 实例</title>
    <!-- 引入 echarts.js -->
    <script src="https://cdn.staticfile.org/echarts/4.3.0/echarts.min.js"></script>
</head>
<body>
    <!-- 为ECharts准备一个具备大小(宽高)的Dom -->
    <div id="main" style="width: 600px;height:400px;"></div>
    <script type="text/javascript">
        // 基于准备好的dom,初始化echarts实例
        var myChart = echarts.init(document.getElementById(main));
 
        // 指定图表的配置项和数据
        var option = 
                legend: ,
                tooltip: ,
                dataset: 
                    source: [
                        [product, 2012, 2013, 2014, 2015],
                        [Matcha Latte, 41.1, 30.4, 65.1, 53.3],
                        [Milk Tea, 86.5, 92.1, 85.7, 83.1],
                        [Cheese Cocoa, 24.1, 67.2, 79.5, 86.4]
                    ]
                ,
                xAxis: [
                    type: category, gridIndex: 0,
                    type: category, gridIndex: 1
                ],
                yAxis: [
                    gridIndex: 0,
                    gridIndex: 1
                ],
                grid: [
                    bottom: 55%,
                    top: 55%
                ],
                series: [
                    // 这几个系列会在第一个直角坐标系中,每个系列对应到 dataset 的每一行。
                    type: bar, seriesLayoutBy: row,
                    type: bar, seriesLayoutBy: row,
                    type: bar, seriesLayoutBy: row,
                    // 这几个系列会在第二个直角坐标系中,每个系列对应到 dataset 的每一列。
                    type: bar, xAxisIndex: 1, yAxisIndex: 1,
                    type: bar, xAxisIndex: 1, yAxisIndex: 1,
                    type: bar, xAxisIndex: 1, yAxisIndex: 1,
                    type: bar, xAxisIndex: 1, yAxisIndex: 1
                ]
            

        // 使用刚指定的配置项和数据显示图表。
        myChart.setOption(option);
    </script>
</body>
</html>

3.2 模板渲染

  • app.py:
import pandas as pd
from flask import Flask, render_template

datas = 
datas2 = 
df = pd.read_csv(data/datum_shift.csv)
df = df.sort_values(AREA_SOUTH_BOUND_LAT, ascending=False)

for item in df.head().values:
    datas[item[0]] = item[1]
    datas2[item[0]] = item[2]
    
app = Flask(__name__)

@app.route(/)
def index():
    return render_template(index.html, datas=datas)

if __name__ == __main__:
    app.run(debug=True)

  • index.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>房源占比前五的饼图</title>
    <script src="./static/js/echarts.min.js"></script>
</head>
<body>
<div id="main" style="width:1000px;height:400px"></div>
<script type="text/javascript">
      // 基于准备好的dom,初始化echarts实例
      var myChart = echarts.init(document.getElementById(main));

      option = 
      title: 
        text: datum_shift,
        subtext: 饼图练习,
        left: center
      ,
      tooltip: 
        trigger: item
      ,
      legend: 
        orient: vertical,
        left: left
      ,
      series: [
        
          name: 各项占比,
          type: pie,
          radius: 50%,
          data: [
               % for data in datas %
               value: datas[data] , name: data,
               % endfor %
          ],
          emphasis: 
            itemStyle: 
              shadowBlur: 10,
              shadowOffsetX: 0,
              shadowColor: rgba(0, 0, 0, 0.5)
            
          
        
      ]
    ;

   // 使用刚指定的配置项和数据显示图表。
   myChart.setOption(option);

</script>
</body>
</html>

3.3 异步请求$.ajax

创建目录如下:

  • test_flask.py:
import json
from flask import Flask, request, jsonify,render_template
app = Flask(__name__)


@app.route(/test)
def hello_world():
    return Hello World,爱看书的小沐!

@app.route("/")
def index():
    return render_template("index.html")

@app.route(/getdata_bar)
def getdata_bar():
    language = [python, java, c, c++, c#, php]
    value = [100, 150, 100, 90, 80, 90]
    return json.dumps(language:language,value:value,ensure_ascii=False) 

@app.route(/getdata_pie)
def getdata_pie():
    data = [
        "value": 235, "name": 视频广告,
        "value": 274, "name": 联盟广告,
        "value": 310, "name": 邮件营销,
        "value": 335, "name": 直接访问,
        "value": 400, "name": 搜索引擎,
        "value": 90, "name": 其他,
    ],

    return json.dumps(data:data,ensure_ascii=False) 

if __name__ == __main__:
    app.run(host="0.0.0.0", port=8080)
  • index.html:
<head>
    <meta charset="UTF-8">
    <title>Echarts</title>
	<script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
    <script src="/static/js/echarts.min.js"></script>

    <style>
        body 
        margin: 100px;
        
        .flex-div
        display: flex;
        width: auto;
        
    </style>
</head>
<body>
    <!-- 为ECharts准备一个具备大小(宽高)的Dom -->
    <div class="flex-div">
    <div id="echarts_lang" style="width: 600px;height:400px;"></div>
    <div id="echarts_ad" style="width: 600px;height:400px;"></div>
    <script type="text/javascript">
         $(function () 
            // 基于准备好的dom,初始化echarts实例
            var myChart = echarts.init(document.getElementById(echarts_lang));
            $.ajax(
                url:/getdata_bar,
                success:function (data) 
                    json_data=JSON.parse(data)

                    console.info(json_data[language])
                    console.info(json_data[value])

                    var option = 
                        title: 
                            text: 人数统计
                        ,
                        tooltip: ,
                        legend: 
                            data:[2022年销量]
                        ,
                        xAxis: 
                            data: json_data[language]
                        ,
                        yAxis: ,
                        series: [
                            name: 2022年销量,
                            type: bar,
                            data: json_data[value]
                        ]
                    ;
                   
                    myChart.setOption(option);
                
            )
        )

        $(function () 
            // 基于准备好的dom,初始化echarts实例
            var myChart = echarts.init(document.getElementById(echarts_ad));
            $.ajax(
                url:/getdata_pie,
                success:function (data) 
                    json_data=JSON.parse(data)
                    console.info(json_data[data])
 
                    option = 
                        series : [
                            
                                name: 访问来源,
                                type: pie,
                                radius: 55%,
                                data: json_data[data][0],
                                roseType: angle,
                                itemStyle: 
                                    normal: 
                                        shadowBlur: 200,
                                        shadowColor: rgba(0, 0, 0, 0.5)
                                    
                                
                            
                        ],
                    ;
                    console.info(option)
                    myChart.setOption(option);
                
            )
        )

    </script>
</body>

3.4 异步请求$.get

  • app.py:
from flask import Flask, request, jsonify,render_template
app = Flask(__name__)

categories=["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
data=[5, 20, 36, 10, 10, 20]
data2=[111, 222, 80, 150, 75, 55]

app = Flask (__name__)

@app.route(/test)
def hello_world():
    return Hello World,爱看书的小沐!

@app.route(/, methods=["GET"])
def index():
     return render_template("index.html")

@app.route(/echarts, methods=["GET"]) 
def echarts():
    return jsonify(categories = categories,data = data, data2 = data2)

if __name__ == __main__:
    app.run(host="0.0.0.0", port=8080)
  • index.html:
<!DOCTYPE html>
<html style="height: 100%" lang="en">

<head>
    <meta charset="utf-8">
    <title>My Finance</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
    <script src="https://cdn.staticfile.org/echarts/4.8.0/echarts.min.js"></script>
    <!-- 引入 vintage 主题 -->
</head>

<body>
    <!-- 为ECharts准备一个具备大小(宽高)的Dom -->
    <div id="main" style="width:1000px;height:300px;"></div>

    <script type="text/javascript">
        // 基于准备好的dom,初始化echarts实例
        var myChart = echarts.init(document.getElementById(main));
        myChart.setOption(
            title: 
                text: $.get异步数据加载示例(爱看书的小沐)
            ,
            tooltip: ,
            legend: 
                data: [1月销量, 2月销量]
            ,
            xAxis: 
                data: []
            ,
            yAxis: ,
            series: [
                name: 1月销量,
                type: bar,
                data: []
            ,
                name: 2月销量,
                type: bar,
                data: []
            ]
        );

        // 异步加载数据
        $.get(/echarts).done(function (data) 
            // 填入数据
            myChart.setOption(
                xAxis: 
                    data: data.categories
                ,
                axisLabel: 
                    show: true,
                    interval: 0,
                    rotate: 40,
                    textStyle: 
                        color: #333
                    
                ,
                series: [
                    
                        name: 1月销量,
                        data: data.data
                    ,
                    
                        name: 2月销量,
                        data: data.data2
                    
                ]
            );
        );

        myChart.setOption(option);
    </script>
</body>

</html>

3.5 Flask + nodejs + vue

对于 Vue 3,你应该使用 npm 上可用的 Vue CLI v4.5 作为 @vue/cli。要升级,你应该需要全局重新安装最新版本的 @vue/cli:

# 全局安装 vue-cli
yarn global add @vue/cli
# 或
cnpm install -g @vue/cli

安装完后查看版本:

$ vue --version

然后在 Vue 项目中运行:

vue upgrade --next

vue create、vue ui、vue init三种方式创建Vue项目。

创建项目:

vue init webpack vue3-test

cd vue3-test
npm run dev

访问网址:http://localhost:8080

npm install --save echarts vue-jsonp vue-resource

  • D:\\0627\\vue3-test\\src\\main.js:
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.

import Vue from vue
import App from ./App.vue
import VueResource from vue-resource
import * as VueJsonp from vue-jsonp
// import echarts from echarts
import * as echarts from echarts;

Vue.use(VueJsonp)
Vue.use(VueResource)
Vue.prototype.$echarts = echarts

new Vue(
    el: #app,
    render: h => h(App)
)

  • D:\\0627\\vue3-test\\src\\App.vue:
<template>
  <div class="main">
    <chart1 />
  </div>
</template>
<script>
import chart1 from "./components/chart1.vue";

export default 
  components: 
    chart1,
  ,
;
</script>
  • D:\\0627\\vue3-test\\src\\components\\chart1.vue:
<template>
  <div>
    <div id="echartContainer" style="width: 100%; height: 500px"></div>
  </div>
</template>

<script>
export default 
  name: "chart1",
  data() 
    return ;
  ,
  methods: 
    draw() 
      var myChart = this.$echarts.init(
        document.getElementById("echartContainer"),
        "infographic"
      );
      myChart.setOption(
        xAxis: ,
        yAxis: ,
        series: [
          
            symbolSize: 5,
            data: [],
            type: "bar",
          ,
        ],
      );
      this.$http
        .get("http://localhost:5000/api/demo/", 
          headers:  "Access-Control-Allow-Origin": "*" ,
        )
        .then((res) => 
          console.log(res.data);
          myChart.hideLoading();
          myChart.setOption( series: [ data: res.data.product ] );
        );
    ,
  ,
  mounted() 
    this.draw();
  ,
;
</script>

<style></style>
  • test_flask:
from flask import Flask, jsonify, render_template
from flask.helpers import make_response
from flask_cors import CORS

app = Flask(__name__,
    static_folder=./dist,  #设置静态文件夹目录
    template_folder = "./dist",
    static_url_path="")  #设置vue编译输出目录dist文件夹,为Flask模板文件目录
CORS(app, resources=r/*)

@app.route(/, methods=["GET"])
def index():
     return render_template("index.html")

@app.route(/api/demo/)
def api_test():
    ans = jsonify(
        "product": [5, 20, 36, 10, 10, 20]
    )
    return make_response(ans)


if __name__ == __main__:
    app.run(debug=True)

cd vue3-test
npm run build
npm run dev

访问:http://localhost:8080/ 以上是开启了两个web服务器(Flask、nodejs). 以下是开一个web服务器(Flask)的方法: 将上面打包的dist文件复制到Flask的主文件夹里,然后运行test_flask.py如下。

结语

如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;╮( ̄▽ ̄)╭ 如果您感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进;o_O??? 如果您需要相关功能的代码定制化开发,可以留言私信作者;(✿◡‿◡) 感谢各位大佬童鞋们的支持!( ´ ▽´ )ノ ( ´ ▽´)っ!!!

<font color=purple face=华文行楷 size="5">"侬今葬花人笑痴,他年葬侬知是谁?"

以上是关于Web开发Python实现Web图表功能(pyecharts,Flask)的主要内容,如果未能解决你的问题,请参考以下文章

Web开发Python实现Web服务器(Flask测试统计图表)

Web开发Python实现Web仪表盘功能(Grafana)

Web开发Node实现Web图表功能(ECharts.js,Vue3)

java web项目中不登录直接访问开源的python superset的图表

(转)基于MVC4+EasyUI的Web开发框架经验总结--使用图表控件Highcharts

Python web 开发购物车修改商品数量功能实现