You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI结合Jinja2模板实现Highcharts图表无刷新自动更新

实现方案

方案1:短轮询(实现成本最低,适合更新频率不高的场景)

步骤1:修改main.py新增数据接口

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
import uvicorn
import random

app = FastAPI()

app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")

# 原有页面接口保留
@app.get("/", response_class=HTMLResponse)
async def dash(request: Request):
    data = [random.randint(0,40) for _ in range(12)]
    return templates.TemplateResponse("dash.html", {"request": request, "title": "my random graph", "tokyo_data": data})

# 新增接口:返回最新的东京温度数据
@app.get("/api/tokyo-data", response_class=JSONResponse)
async def get_tokyo_data():
    # 这里替换成你的数据库查询逻辑
    latest_data = [random.randint(0,40) for _ in range(12)]
    return {"data": latest_data}

if __name__ == '__main__':
    uvicorn.run("main:app", port=80, host='0.0.0.0', reload = True)

步骤2:修改templates/dash.html添加自动更新逻辑

<html>
   <head>
      <title>my random graph</title>
      <script src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js">
      </script>
      <script src = "https://code.highcharts.com/highcharts.js"></script> 
   </head>
   
   <body>
      <div id = "container" style = "width: 550px; height: 400px; margin: 0 auto"></div>
      <script language = "JavaScript">
         // 全局存储图表实例,方便后续更新
         let chartInstance = null;

         $(document).ready(function() {
            var title = {
               text: "{{ title }}"
            };
            var credits = {
                  enabled: false
            };
            var subtitle = {
               text: 'test'
            };
            var xAxis = {
               categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                  'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
            };
            var yAxis = {
               title: {
                  text: 'Temperature (\xB0C)'
               },
               plotLines: [{
                  value: 0,
                  width: 1,
                  color: '#808080'
               }]
            };   

            var tooltip = {
               valueSuffix: '\xB0C'
            }
            var legend = {
               layout: 'vertical',
               align: 'right',
               verticalAlign: 'middle',
               borderWidth: 0
            };
            var series =  [{
                  name: 'Tokyo',
                  data: {{ tokyo_data }}
               }, 
               {
                  name: 'New York',
                  data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 
                     24.1, 20.1, 14.1, 8.6, 2.5]
               }, 
               {
                  name: 'Berlin',
                  data: [-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6,
                     17.9, 14.3, 9.0, 3.9, 1.0]
               }, 
               {
                  name: 'London',
                  data: [3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 
                     16.6, 14.2, 10.3, 6.6, 4.8]
               }
            ];

            var json = {};
            json.title = title;
            json.subtitle = subtitle;
            json.xAxis = xAxis;
            json.yAxis = yAxis;
            json.tooltip = tooltip;
            json.legend = legend;
            json.series = series;
            json.credits = credits;

            // 初始化图表并保存实例
            chartInstance = $('#container').highcharts(json);
         });

         // 每3秒拉取一次最新数据,更新图表
         setInterval(async () => {
            if (!chartInstance) return;
            const res = await fetch('/api/tokyo-data');
            const { data: latestData } = await res.json();
            // 如果需要仅数据变化时更新,可以在这里和本地存储的上一次数据对比后再执行更新
            // 更新东京系列的数据,第二个参数设为true表示自动重绘
            chartInstance.series[0].setData(latestData, true);
         }, 3000);
      </script>
   </body>
   
</html>

方案2:WebSocket(实时性更高,适合数据更新频繁的场景)

如果需要数据更新后立即推送,不需要定时轮询,可以用FastAPI的WebSocket支持:

步骤1:修改main.py新增WebSocket路由

from fastapi import FastAPI, Request, WebSocket
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
import uvicorn
import random
import asyncio
from typing import List

app = FastAPI()

app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")

# 存储所有连接的客户端
active_connections: List[WebSocket] = []

@app.get("/", response_class=HTMLResponse)
async def dash(request: Request):
    data = [random.randint(0,40) for _ in range(12)]
    return templates.TemplateResponse("dash.html", {"request": request, "title": "my random graph", "tokyo_data": data})

@app.websocket("/ws/data-update")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    active_connections.append(websocket)
    try:
        while True:
            # 这里可以替换为监听数据库更新的逻辑,比如数据库触发器、消息队列通知等
            latest_data = [random.randint(0,40) for _ in range(12)]
            await websocket.send_json({"data": latest_data})
            await asyncio.sleep(3)
    finally:
        active_connections.remove(websocket)

if __name__ == '__main__':
    uvicorn.run("main:app", port=80, host='0.0.0.0', reload = True)

步骤2:修改前端JS代码替换轮询为WebSocket连接

把之前的setInterval部分替换为以下代码即可:

// 建立WebSocket连接
const ws = new WebSocket(`ws://${window.location.host}/ws/data-update`);
ws.onmessage = (event) => {
    if (!chartInstance) return;
    const { data: latestData } = JSON.parse(event.data);
    chartInstance.series[0].setData(latestData, true);
};

内容的提问来源于stack exchange,提问作者Zabir Al Nazi Nabil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 00:24:06