《用 python、MySQL 和 Chart.js 打造炫酷数据看板》实战案例笔记

今天,我们要构建一个数据看板系统。在这个过程中,我们会利用 MySQL 来存储数据,使用 Python 搭建后端 API,还会借助 Chart.js 在前端呈现各式各样的图表。

整个流程涵盖多个环节,首先要进行数据库表的设计,接着将数据插入到数据库中,然后搭建后端的数据接口,最后在前端通过 JavaScript 动态渲染图表,如此便形成了完整的数据看板系统。

1. 安装依赖

在运行代码前,确保安装了必要的 Python 依赖:

复制代码
pip install flask pymysql

2. 创建 MySQL 数据表

运行以下 SQL 代码,创建用于存储数据的 your_table 表:

复制代码
CREATE TABLE kb (
    id INT AUTO_INCREMENT PRIMARY KEY,
    category VARCHAR(50),
    year INT,
    month INT,
    value INT
);

3. 数据库插入数据

运行以下 SQL 代码,插入数据:

复制代码
INSERT INTO kb (category, year, month, value) VALUES ('人事', 2023, 1, 399);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2023, 1, 410);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2023, 1, 208);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2023, 2, 291);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2023, 2, 172);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2023, 2, 199);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2023, 3, 370);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2023, 3, 454);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2023, 3, 207);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2023, 4, 397);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2023, 4, 228);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2023, 4, 151);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2023, 5, 373);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2023, 5, 429);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2023, 5, 307);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2023, 6, 485);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2023, 6, 419);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2023, 6, 468);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2023, 7, 169);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2023, 7, 185);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2023, 7, 289);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2023, 8, 282);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2023, 8, 232);
INSERTINTO kb (category, year, month, value) VALUES ('财务', 2023, 8, 339);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2023, 9, 269);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2023, 9, 274);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2023, 9, 435);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2023, 10, 463);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2023, 10, 108);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2023, 10, 295);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2023, 11, 168);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2023, 11, 351);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2023, 11, 162);
INSERTINTO kb (category, year, month, value) VALUES ('财务', 2023, 12, 395);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2023, 12, 428);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2023, 12, 339);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2024, 1, 192);
INSERTINTO kb (category, year, month, value) VALUES ('财务', 2024, 1, 156);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 1, 130);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2024, 2, 442);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2024, 2, 149);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2024, 2, 460);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 3, 293);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2024, 3, 228);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2024, 3, 231);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2024, 4, 288);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2024, 4, 242);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 4, 205);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 5, 491);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2024, 5, 144);
INSERTINTO kb (category, year, month, value) VALUES ('财务', 2024, 5, 255);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2024, 6, 128);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2024, 6, 439);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 6, 177);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2024, 7, 486);
INSERTINTO kb (category, year, month, value) VALUES ('财务', 2024, 7, 411);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2024, 7, 338);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 8, 456);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2024, 8, 93);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2024, 8, 63);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2024, 9, 149);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 9, 248);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2024, 9, 158);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2024, 10, 255);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2024, 10, 493);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2024, 10, 234);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2024, 11, 383);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 11, 128);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 11, 116);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2024, 12, 438);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 12, 449);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2024, 12, 426);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2025, 1, 171);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2025, 1, 270);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2025, 1, 350);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2025, 2, 351);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2025, 2, 260);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2025, 2, 186);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2025, 3, 51);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2025, 3, 410);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2025, 3, 294);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2025, 4, 495);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2025, 4, 436);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2025, 4, 363);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2025, 5, 406);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2025, 5, 149);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2025, 5, 329);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2025, 6, 187);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2025, 6, 490);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2025, 6, 471);
INSERTINTO kb (category, year, month, value) VALUES ('财务', 2025, 7, 387);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2025, 7, 481);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2025, 7, 249);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2025, 8, 177);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2025, 8, 160);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2025, 8, 423);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2025, 9, 111);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2025, 9, 131);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2025, 9, 426);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2025, 10, 448);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2025, 10, 317);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2025, 10, 58);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2025, 11, 311);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2025, 11, 343);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2025, 11, 284);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2025, 12, 312);
INSERTINTO kb (category, year, month, value) VALUES ('财务', 2025, 12, 95);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2025, 12, 400);

4. python后端(server.py

python 复制代码
from flask import Flask, jsonify, render_template
import pymysql.cursors

app = Flask(__name__)

# 连接 MySQL 数据库
def get_db_connection():
    return pymysql.connect(
        host="localhost",
        user="root",  # 修改为你的数据库用户名
        password="root",  # 修改为你的数据库密码
        database="demo2",  # 修改为你的数据库名称
        port=3306,
        cursorclass=pymysql.cursors.DictCursor
    )




# API:获取数据
@app.route("/api/data")
def get_data():
    connection = get_db_connection()
    with connection.cursor() as cursor:
        cursor.execute("SELECT year, month, category, value FROM kb ORDER BY year, month")
        data = cursor.fetchall()
    connection.close()
    return jsonify(data)

# 前端页面
@app.route("/")
def index():
    return render_template("index.html")

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

5. 前端页面(templates/index.html)

templates/ 目录下创建 index.html 文件:

html 复制代码
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>数据看板</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>
        body {
            font-family: 'Arial', sans-serif;
            background: linear-gradient(to right, #141e30, #243b55);
            color: white;
            text-align: center;
            padding: 20px;
        }
        h2 {
            font-size: 2rem;
            margin-bottom: 20px;
        }
        .chart-container {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 20px;
            justify-items: center;
            padding: 20px;
        }
        .chart-box {
            width: 1000px;      /* 根据需求可继续调大或调小 */
            height: 500px;     /* 根据需求可继续调大或调小 */
            background: rgba(255, 255, 255, 0.1);
            padding: 20px;
            border-radius: 15px;
            box-shadow: 0px 0px 15px rgba(255, 255, 255, 0.3);
            transition: transform 0.3s;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .chart-box:hover {
            transform: scale(1.05);
        }
        canvas {
            width: 100% !important;
            height: 100% !important;
        }
    </style>
</head>
<body>
    <h2>✨ 数据看板 ✨</h2>
    <div class="chart-container">
        <div class="chart-box"><canvas id="barChart"></canvas></div>
        <div class="chart-box"><canvas id="pieChart"></canvas></div>
        <div class="chart-box"><canvas id="lineChart"></canvas></div>
        <div class="chart-box"><canvas id="scatterChart"></canvas></div>
    </div>
    <script>
        fetch('/api/data')
            .then(response => response.json())
            .then(data => {
                // 1. 准备数据
                const categories = [...new Set(data.map(item => item.category))];
                const months = Array.from({ length: 12 }, (_, i) => `${i + 1}月`);

                let datasetMap = {};
                categories.forEach(category => {
                    datasetMap[category] = Array(12).fill(0);
                });

                data.forEach(item => {
                    datasetMap[item.category][item.month - 1] = item.value;
                });

                // 2. 随机色
                const colors = categories.map(() => `hsl(${Math.random()*360}, 80%, 60%)`);

                // 3. 柱状图
                const ctxBar = document.getElementById('barChart').getContext('2d');
                new Chart(ctxBar, {
                    type: 'bar',
                    data: {
                        labels: months,
                        datasets: categories.map((category, i) => ({
                            label: category,
                            data: datasetMap[category],
                            backgroundColor: colors[i],
                            borderColor: 'white',
                            borderWidth: 1
                        }))
                    },
                    options: { responsive: true }
                });

                // 4. 饼图
                const ctxPie = document.getElementById('pieChart').getContext('2d');
                new Chart(ctxPie, {
                    type: 'doughnut',
                    data: {
                        labels: categories,
                        datasets: [{
                            data: categories.map(category => datasetMap[category].reduce((a, b) => a + b, 0)),
                            backgroundColor: colors,
                            borderColor: 'white'
                        }]
                    },
                    options: { responsive: true }
                });

                // 5. 折线图(鼠标悬浮时显示数值)
                const ctxLine = document.getElementById('lineChart').getContext('2d');
                new Chart(ctxLine, {
                    type: 'line',
                    data: {
                        labels: months,
                        datasets: categories.map((category, i) => ({
                            label: category,
                            data: datasetMap[category],
                            borderColor: colors[i],
                            fill: false,
                            tension: 0.4,
                            pointBackgroundColor: 'white'
                        }))
                    },
                    options: {
                        responsive: true,
                        // 关键:鼠标悬浮显示数值
                        interaction: {
                            mode: 'index',
                            intersect: false
                        },
                        plugins: {
                            tooltip: {
                                enabled: true,
                                callbacks: {
                                    // 回调函数,自定义显示的文本
                                    label: function(context) {
                                        let label = context.dataset.label || '';
                                        let value = context.parsed.y !== undefined ? context.parsed.y : '';
                                        return `${label}: ${value}`;
                                    }
                                }
                            }
                        }
                    }
                });

                // 6. 散点图
                const ctxScatter = document.getElementById('scatterChart').getContext('2d');
                new Chart(ctxScatter, {
                    type: 'scatter',
                    data: {
                        datasets: categories.map((category, i) => ({
                            label: category,
                            data: datasetMap[category].map((value, index) => ({ x: index + 1, y: value })),
                            backgroundColor: colors[i],
                            borderColor: 'white',
                            pointRadius: 6
                        }))
                    },
                    options: { responsive: true }
                });
            })
            .catch(error => console.error('数据加载失败:', error));
    </script>
</body>
</html>

6. 运行 Flask 服务器

复制代码
python server.py

然后打开浏览器,访问:

复制代码
http://127.0.0.1:5000

点击阅读原文:《用 python、MySQL 和 Chart.js 打造炫酷数据看板》实战案例笔记

原创 IT小本本 IT小本本 2025年03月11日 21:21 北京

最终效果:

相关推荐
青 春 记 忆3 小时前
Dify Docker Compose 通用无损升级指南:从备份、双版本预演到切换与回滚
运维·人工智能·python·docker·容器
GlueNa2SiO33 小时前
03-Flask模板引擎Jinja2详解
笔记·python·flask
临沂GEO5 小时前
GEO搜索优化科普|正规地理位置流量运营入门指南
大数据·人工智能·python·流量运营
大模型码小白6 小时前
Spring AI Tool 实现自然语言操作 MySQL 数据库详解
服务器·开发语言·数据库·人工智能·python·mysql·spring
荷蒲7 小时前
【小白量化Qbuddy】利用AI学习中文Python
人工智能·python·学习
数据狐(Datafox)8 小时前
京东商品列表API技术解析与落地应用(含标准 JSON 示例)
java·大数据·前端·人工智能·python·数据分析·json
量化吞吐机9 小时前
2026年下半年手工交易规则走向量化表达,产品该先接住哪一步
人工智能·python
Metaphor6929 小时前
使用 Python 读取和删除 Excel 文件属性
python·excel
迷迭香yy10 小时前
Python构建转融券多空识别系统从接口到因子的全流程 IG50免费开源股票数据API接口
开发语言·python·开源
月光船幽幽11 小时前
真实即粗糙,光滑是伪造
人工智能·python