前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于pyecharts可视化与Flask相结合

关于pyecharts可视化与Flask相结合

作者头像
python与大数据分析
发布2022-03-11 14:34:10
1.2K0
发布2022-03-11 14:34:10
举报
文章被收录于专栏:python与大数据分析

关于pyecharts和flask结合的案例不多,查阅了数十篇文章,尝试了若干遍,感觉还是不理想,最大的问题在于对echarts的理解上,对我而言,又需要向上推到ajax,jquery,bootstrap,html,css,javascript等等,有点超出了我的技能范围,所以最大程度的做到能用就够了,复用和进一步优化看起来还是遥遥无期。

关于pyecharts可视化与中国经济、人口等数据系列的笔记也暂时告以段落了。

Flask 模板渲染

Step 0: 新建一个 Flask 项目

mkdir pyecharts-flask-demo

cd pyecharts-flask-demo

mkdir templates

Step 1: 拷贝 pyecharts 模板

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

|--components.html

|--macro

|--nb_components.html

|--nb_jupyter_globe.html

|--nb_jupyter_lab.html

|--nb_jupyter_lab_tab.html

|--nb_jupyter_notebook.html

|--nb_jupyter_notebook_tab.html

|--nb_nteract.html

|--simple_chart.html

|--simple_globe.html

|--simple_page.html

|--simple_tab.html

Step 2: 渲染图表

在项目的根目录下新建server.py

一种是把图表render到templates目录下

一种是直接使用render_embed方式

Flask 前后端分离

前后端分离可以使用动态更新数据,增量更新数据等功能。

Step 0,Step 1 参见上面模板渲染章节内容

Step 3: 新建一个 HTML 文件, 新建 HTML 文件保存位于项目根目录的 templates 文件夹

Step 4: 编写 flask 和 pyecharts 代码渲染图表,将代码保存项目的根目录下。

定时全量更新图表

前端主动向后端进行数据刷新

定时刷新的核心在于 HTML 的 setInterval 方法。

带参数访问方式,也是采用render_embed方式,只不过是把参数又传递给图表了

代码语言:javascript
复制
import os
from random import randrange

from flask.json import jsonify
from flask importFlask
from flask import render_template
from jinja2 importMarkup, Environment, FileSystemLoader
import random
from flask importFlask, render_template
from flask import request

from pyecharts.globals importCurrentConfig
from pyecharts.faker importFaker
from pyecharts import options as opts
from pyecharts.charts importBar,Line
from pyecharts import options as opts
from pyecharts.charts importGauge, Page,Map,Scatter

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

# render()方法:默认会在当前目录生成 render.html 文件
# render()方法传入路径参数:传入路径参数,如 bar.render(“mycharts.html”),这种方法好一点,可以设定文件路径
# render_notebook()方法:这个方法可用在notebook中
# render_embed()方法:来自pyecharts的flask一章中的Markup(c.render_embed())
# chart.dump_options()方法:这个方法能和flask配合不错,能够实现一个flask网页中绘制很多个图表;
# 然而却依然需要自己引入echarts.js文件、自己设定div、自己初始化echarts对象、自己给echarts对象设置图表配置,唯一简化的就是图表配置是来自于python服务端;
# 获取全局 options,JSON 格式(JsCode生成的函数不带引号)
# def dump_options() -> str:
# 获取全局 options,JSON 格式(JsCode生成的函数带引号,在前后端分离传输数据时使用)
# def dump_options_with_quotes() -> str:
# 从实际执行的角度,这两种方法暂时没发现有什么区别,先人云亦云的练习吧

# 生成bart图
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


# 生成line图
def line_base() -> Line:
    c = (
Line()
.add_xaxis(Faker.choose())
.add_yaxis("商家A", Faker.values())
.add_yaxis("商家B", Faker.values())
.set_global_opts(title_opts=opts.TitleOpts(title="Line-基本示例"))
)
return c


# 仪表盘图
def gauge_base() -> Gauge:
    c = (
Gauge()
.add("", [("完成率", 66.6)])
.set_global_opts(title_opts=opts.TitleOpts(title="Gauge-基本示例"))
)
return c


# 地图map
def map_base() -> Map:
    c = (
Map()
.add("商家A", [list(z) for z in zip(Faker.provinces, Faker.values())], "china")
.set_global_opts(title_opts=opts.TitleOpts(title="Map-基本示例"))
)
return c


#散点图
def scatter_base() -> Scatter:
    c = (
Scatter()
.add_xaxis(Faker.choose())
.add_yaxis("商家A", Faker.values())
.set_global_opts(title_opts=opts.TitleOpts(title="Scatter-基本示例"))
)
return c


#  新增全量更新数据
def full_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


#  新增动态更新数据
def incre_line_base() -> Line:
    line = (
Line()
.add_xaxis(["{}".format(i) for i in range(10)])     #初始化10个值
.add_yaxis(
            series_name="",
            y_axis=[randrange(50, 80) for _ in range(10)],  #在50-80循环出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


# 生成bart图,带参数
def bar_base_withpara(title,ydata) -> Bar:
    c = (
Bar()
.add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"])
.add_yaxis("商家A", ydata)
.set_global_opts(title_opts=opts.TitleOpts(title=title, subtitle="动态标题"))
)
return c


# render_embed方法
@app.route("/render_embed")
def render_embed():
    c = bar_base()
returnMarkup(c.render_embed())


# render到文件方法,注意render的缺省工作目录和flask的template工作目录不同
@app.route("/render")
def renderhtml():
    filename='terenderfile.html'
    currentpath=os.path.abspath('.')
    pathfilename=os.path.join(currentpath, 'templates',filename)
    c = line_base()
    c.render(pathfilename)
return render_template(filename)


# 外部访问链路
@app.route('/')
def hello_world():
return'Hello World'

# ----------------------------------------------------------
# 经测试bar,line,scatter和gauge可通过ajax + url: "http://127.0.0.1:8080/XXXChart"方式
# 但Map不行,估计是map访问的百度地图资源受限,待核查
# ----------------------------------------------------------

# 外部访问链路,bar图
@app.route("/dumpbar")
def dump_bar():
return render_template("barbaseindex.html")


# barbaseindex.html指向的链路
@app.route("/barChart")
def get_bar_chart():
    c = bar_base()
return c.dump_options_with_quotes()


# 外部访问链路,line图
@app.route("/dumpline")
def dump_line():
return render_template("linebaseindex.html")


# linebaseindex.html指向的链路
@app.route("/lineChart")
def get_line_chart():
    c = line_base()
return c.dump_options_with_quotes()


# 外部访问链路,scatter图
@app.route("/dumpscatter")
def dump_scatter():
return render_template("scatterbaseindex.html")


# scatterbaseindex.html指向的链路
@app.route("/scatterChart")
def get_scatter_chart():
    c = scatter_base()
return c.dump_options_with_quotes()


# 外部访问链路,gauge图
@app.route("/dumpgauge")
def dump_gauge():
return render_template("gaugebaseindex.html")


# gaugebaseindex.html指向的链路
@app.route("/gaugeChart")
def get_gauge_chart():
    c = gauge_base()
return c.dump_options()
#return c.dump_options_with_quotes()


# 通过mapbaseindex.html对http://127.0.0.1:8080/mapChart"调用,只能看到标题,无法打开地图
# # 外部访问链路,map图
# @app.route("/dumpmap")
# def dump_map():
#     return render_template("mapbaseindex.html")
#
# # mapbaseindex.html指向的链路
# @app.route("/mapChart")
# def get_map_chart():
#     c = map_base()
#     return c.dump_options_with_quotes()


# 外部访问链路,bar图
@app.route("/dumpfullbar")
def dump_full_bar():
return render_template("fullupdatebarbase.html")


# barbaseindex.html指向的链路
@app.route("/fullbarChart")
def get_full_bar_chart():
    c = full_bar_base()
return c.dump_options_with_quotes()


# 外部访问链路,动态新增值的line图
@app.route("/dumpincreline")
def index():
return render_template("increupdatelinebase.html")


# increupdatelinebase.html指向的链路
@app.route("/increlineChart")
def get_incre_line_chart():
    c = incre_line_base()
return c.dump_options_with_quotes()


idx = 9
# 生成动态新增数据值,在increupdatelinebase.html的http://127.0.0.1:8080/lineDynamicData被引用
@app.route("/lineDynamicData")
def update_line_data():
    global idx
    idx = idx + 1
return jsonify({"name": idx, "value": randrange(50, 80)})   



@app.route("/dumpbarwithpara")
def dump_bar_withpara():
return render_template("barbasewithparaindex.html")


@app.route("/barChartwithpara", methods=['post','get'])
def get_bar_chart_withpara():
    title = request.args.get('title')
    type = request.args.get('type')
    ydata=list(randrange(1,100) for i in range(6))
    c = bar_base_withpara(title, ydata)
returnMarkup(c.render_embed())



if __name__ == "__main__":
    app.run('127.0.0.1', '8080', debug=True)

关于barbaseindex.html文件

代码示例

代码语言:javascript
复制
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Awesome-pyecharts</title>
    <script src="templates/jquery-3.4.1.min.js"></script>
    <script type="text/javascript" src="templates/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:8080/fullbarChart",
                dataType: 'json',
                success: function (result) {
                    chart.setOption(result);
                }
            });
        }
    </script>
</body>
</html>
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-02-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 python与大数据分析 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 代码示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档