zoukankan      html  css  js  c++  java
  • flask+sqlite3+echarts3+ajax 异步更新数据

    结构:
    /www
    |
    |-- /static
    |....|-- jquery-3.1.1.js
    |....|-- echarts.js(echarts3是单文件!!)
    |
    |-- /templates
    |....|-- index.html
    |
    |-- app.py
    |
    |-- create_db.py

    一、先准备数据

    # create_db.py
    # 只运行一次!!!
    
    import sqlite3
    
    # 连接
    conn = sqlite3.connect('mydb.db')
    c = conn.cursor()
    
    # 创建表
    c.execute('''DROP TABLE IF EXISTS weather''')
    c.execute('''CREATE TABLE weather (month text, evaporation text, precipitation text)''')
    
    # 数据
    # 格式:月份,蒸发量,降水量
    purchases = [('1月', 2, 2.6),
                 ('2月', 4.9, 5.9),
                 ('3月', 7, 9),
                 ('4月', 23.2, 26.4),
                 ('5月', 25.6, 28.7),
                 ('6月', 76.7, 70.7),
                 ('7月', 135.6, 175.6),
                 ('8月', 162.2, 182.2),
                 ('9月', 32.6, 48.7),
                 ('10月', 20, 18.8),
                 ('11月', 6.4, 6),
                 ('12月', 3.3, 2.3)
                ]
    
    # 插入数据
    c.executemany('INSERT INTO weather VALUES (?,?,?)', purchases)
    
    # 提交!!!
    conn.commit()
    
    # 查询方式一
    for row in c.execute('SELECT * FROM weather'):
        print(row)
        
        
    # 查询方式二
    c.execute('SELECT * FROM weather')
    print(c.fetchall())
    
    
    # 查询方式二_2
    res = c.execute('SELECT * FROM weather')
    print(res.fetchall())
    
    
    # 关闭
    conn.close()
    
    

    二、定义路由

    第一次性加载六条数据
    以后,每隔1秒更新一条数据

    由如下函数实现:

    @app.route("/weather", methods=["GET","POST"])
    def weather():
        if request.method == "GET":
            res = query_db("SELECT * FROM weather WHERE id <= 6") #不妨设定:第一次只返回6个数据
        elif request.method == "POST":
            res = query_db("SELECT * FROM weather WHERE id = (?)", args=(int(request.form['id'])+1,)) #以后每次返回1个数据
            #res = query_db("SELECT * FROM weather WHERE id = 13") # 一个不存在的记录
        
        return jsonify(month = [x[1] for x in res],
                       evaporation = [x[2] for x in res], 
                       precipitation = [x[3] for x in res]) # 返回json格式
    

    此函数用于处理ajax,返回json格式。形如:

    {
        month: ['1月','2月',...],
        evaporation: [3.1, 4, 4.6, ...],
        precipitation: [...]
    }
    

    完整app.py文件:

    import sqlite3
    from flask import Flask, request, render_template, jsonify
    
    app = Flask(__name__)
    
    
    def get_db():
        db = sqlite3.connect('mydb.db')
        db.row_factory = sqlite3.Row
        return db
    
    
    def query_db(query, args=(), one=False):
        db = get_db()
        cur = db.execute(query, args)
        db.commit()
        rv = cur.fetchall()
        db.close()
        return (rv[0] if rv else None) if one else rv
    
    
    @app.route("/", methods=["GET"])
    def index():
        return render_template("index.html")
    
    
    @app.route("/weather", methods=["GET","POST"])
    def weather():
        if request.method == "GET":
            res = query_db("SELECT * FROM weather WHERE id <= 6") #不妨设定:第一次只返回6个数据
        elif request.method == "POST":
            res = query_db("SELECT * FROM weather WHERE id = (?)", args=(int(request.form['id'])+1,)) #以后每次返回1个数据
            #res = query_db("SELECT * FROM weather WHERE id = 13") # 一个不存在的记录
        
        return jsonify(month = [x[1] for x in res],
                       evaporation = [x[2] for x in res], 
                       precipitation = [x[3] for x in res]) # 返回json格式
    
    
    if __name__ == "__main__":
        app.run(debug=True)
    

    三、使用echarts

    官网对eccharts 3数据动态更新的描述:

    ···
    数据的动态更新

    ECharts 由数据驱动,数据的改变驱动图表展现的改变,因此动态数据的实现也变得异常简单。

    所有数据的更新都通过 setOption实现,你只需要定时获取数据,setOption 填入数据,而不用考虑数据到底产生了那些变化,ECharts 会找到两组数据之间的差异然后通过合适的动画去表现数据的变化。

    > ECharts 3 中移除了 ECharts 2 中的 addData 方法。如果只需要加入单个数据,可以先 data.push(value) 后 setOption
    

    ···

    index.html文件如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <title>ECharts3 Ajax</title>
        <script src="{{ url_for('static', filename='jquery-3.1.1.js') }}"></script>
        <script src="{{ url_for('static', filename='echarts.js') }}"></script>
    </head>
    
    <body>
        <!--为ECharts准备一个具备大小(宽高)的Dom-->
        <div id="main" style="height:500px;border:1px solid #ccc;padding:10px;"></div>
        
        <script type="text/javascript">
        //--- 折柱 ---
        var myChart = echarts.init(document.getElementById('main'));
        
        myChart.setOption({
            title: {
                text: '异步数据更新示例'
            },
            tooltip: {},
            legend: {
                data:['蒸发量','降水量']
            },
            xAxis: {
                data: []
            },
            yAxis: {},
            series: [{
                name: '蒸发量',
                type: 'bar',
                data: []
            },{
                name: '降水量',
                type: 'line',
                data: []
            }]
        });
        
        
        // 四个全局变量:月份、蒸发量、降水量、  哨兵(用于POST)
        var month = [],
            evaporation = [],
            precipitation = [],
            
            lastID = 0; // 哨兵,记录上次数据表中的最后id +1(下次查询只要>=lastID)
    
        
        //准备好统一的 callback 函数
        var update_mychart = function (data) { //data是json格式的response对象
            
            myChart.hideLoading(); // 隐藏加载动画
            
            dataLength = data.month.length //取回的数据长度
            lastID += dataLength //哨兵,相应增加。
            
            // 切片是能统一的关键!!
            month = month.slice(dataLength).concat(data.month) // 数组,先切片、再拼接
            evaporation = evaporation.slice(dataLength).concat(data.evaporation.map(parseFloat)) //注意map方法
            precipitation = precipitation.slice(dataLength).concat(data.precipitation.map(parseFloat))
            
            // 填入数据
            myChart.setOption({
                xAxis: {
                    data: month
                },
                series: [{
                    name: '蒸发量', // 根据名字对应到相应的系列
                    data: evaporation
                },{
                    name: '降水量',
                    data: precipitation
                }]
            });
            
            if (dataLength == 0){clearInterval(timeTicket);} //如果取回的数据长度为0,停止ajax
        }
        
        myChart.showLoading(); // 首次显示加载动画
        
        
        // 异步加载数据 (首次,get,显示6个数据)
        $.get('/weather').done(update_mychart);
        
        
        // 异步更新数据 (以后,定时post,取回1个数据)
        var timeTicket = setInterval(function () {
            $.post('/weather',{id: lastID}).done(update_mychart);
        }, 5000);
        
        </script>
    </body>
    </html>
    

    效果图:

  • 相关阅读:
    109 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 03 新增功能及实现 05 问题解析--通过一个方法完成学生和专业的双向关联
    108 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 03 新增功能及实现 04 问题解析--数组未实例化造成的空指针异常
    107 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 03 新增功能及实现 03 编写方法完成学生个数统计功能
    106 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 03 新增功能及实现 02 新增属性完成学生信息存储
    105 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 03 新增功能及实现 01 新增需求及分析
    session与cookie的区别和联系
    session和cookie的区别
    Web服务器主动推送技术
    webSocket的场景应用
    TCP、Http和Socket 优劣比较
  • 原文地址:https://www.cnblogs.com/hhh5460/p/6010500.html
Copyright © 2011-2022 走看看