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

如何在Jinja2模板中用JavaScript动态获取解析JSON并定时更新页面?

Flask + JavaScript 实现定时拉取JSON并动态更新页面内容

现有代码的核心问题

  1. API路由不匹配:前端JS请求的是/api/posts,但后端Flask只配置了/api/post路由,导致请求失败。
  2. 定时间隔不符合需求:你要求5秒更新一次,但JS里设置的是2000ms(2秒)。
  3. 数据格式不兼容:前端JS期望返回的JSON包含posts字段,但后端load_posts()如果直接返回帖子数组,会导致data.posts为undefined,无法遍历。
  4. 表单提交会刷新页面:默认表单提交是同步请求,会导致页面刷新,破坏实时更新的体验。

修正后的后端Flask代码

from flask import Flask, render_template, request, jsonify
from datetime import datetime
from utils import *

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html', posts=load_posts()["posts"])  # 确保传递的是帖子数组

@app.route('/api/post', methods=['POST', 'GET'])
def handle_post():
    if request.method == 'POST':
        create_new_post(
            content=request.form['content'],
            date=datetime.now().strftime("%B %d, %Y"),
            author=request.form['author']
        )
        return jsonify({"status": "success"}), 201  # 返回JSON格式响应
    else:
        # 确保返回的JSON包含posts字段,匹配前端期望的结构
        return jsonify(load_posts())

app.run(host='127.0.0.1', port=8080, debug=True)

注意:确保你的load_posts()函数返回的是类似{"posts": [{"author": "...", "content": "...", "date": "..."}]}的JSON结构,如果之前不是,需要修改utils.py里的实现。


修正后的前端HTML/JavaScript代码

<!DOCTYPE html>
<html>
<head>
    <style>
        /* 保留原CSS样式并优化细节 */
        body {
            background-color: #1c1e21;
            color: #ffffff;
            font-family: Arial, sans-serif;
            margin: 20px;
        }

        .post-container {
            background-color: #323739;
            padding: 15px;
            margin-bottom: 12px;
            border-radius: 4px;
        }

        .post-content {
            margin-top: 8px;
            line-height: 1.4;
        }

        .post-author {
            font-weight: bold;
            margin-bottom: 4px;
            color: #009688;
        }

        .post-date {
            color: #8b8d92;
            font-size: 12px;
            margin-top: 8px;
        }

        .new-post-container {
            background-color: #323739;
            padding: 15px;
            margin-bottom: 12px;
            border-radius: 4px;
        }

        .new-post-input {
            width: 100%;
            height: 100px;
            resize: none;
            background-color: #2a2e31;
            color: #fff;
            border: none;
            padding: 8px;
            border-radius: 4px;
            box-sizing: border-box;
            margin-bottom: 8px;
        }

        .new-post-input[type="text"] {
            height: 40px;
        }

        .new-post-button {
            background-color: #009688;
            color: #fff;
            border: none;
            padding: 8px 16px;
            cursor: pointer;
            border-radius: 4px;
        }

        .new-post-button:hover {
            background-color: #00796b;
        }
    </style>
    <script>
        // 定时拉取并更新帖子
        function updatePosts() {
            fetch('/api/post')
                .then(response => {
                    if (!response.ok) throw new Error('请求失败');
                    return response.json();
                })
                .then(data => {
                    const postsContainer = document.getElementById('posts-container');
                    postsContainer.innerHTML = '';

                    // 遍历帖子数据生成DOM元素
                    data.posts.forEach(post => {
                        const postElement = document.createElement('div');
                        postElement.className = 'post-container';
                        postElement.innerHTML = `
                            <div class="post-author">${post.author}</div>
                            <div class="post-content">${post.content}</div>
                            <div class="post-date">${post.date}</div>
                        `;
                        postsContainer.appendChild(postElement);
                    });

                    // 5秒后再次执行更新
                    setTimeout(updatePosts, 5000);
                })
                .catch(error => {
                    console.error('拉取帖子失败:', error);
                    // 即使出错也继续定时更新
                    setTimeout(updatePosts, 5000);
                });
        }

        // 表单AJAX提交,避免页面刷新
        document.addEventListener('DOMContentLoaded', () => {
            const postForm = document.querySelector('.new-post-container');
            postForm.addEventListener('submit', (e) => {
                e.preventDefault(); // 阻止默认表单提交行为

                const formData = new FormData(postForm);
                fetch('/api/post', {
                    method: 'POST',
                    body: formData
                })
                .then(response => response.json())
                .then(data => {
                    if (data.status === 'success') {
                        postForm.reset(); // 重置表单
                        // 立即触发一次更新,不用等5秒
                        updatePosts();
                    }
                })
                .catch(error => console.error('发布帖子失败:', error));
            });

            // 启动首次更新
            updatePosts();
        });
    </script>       
</head>
<body>
    <form class="new-post-container">
        <textarea class="new-post-input" name="content" placeholder="输入帖子内容"></textarea>
        <input class="new-post-input" type="text" name="author" placeholder="你的名字">
        <button class="new-post-button" type="submit">发布</button>
    </form>

    <div id="posts-container">
        {% for post in posts %}
            <div class="post-container">
                <div class="post-author">{{ post["author"] }}</div>
                <div class="post-content">{{ post["content"] }}</div>
                <div class="post-date">{{ post["date"] }}</div>
            </div>
        {% endfor %}
    </div>    
</body>
</html>

关键实现说明

  1. Jinja2与动态更新的关系:Jinja2是服务器端渲染工具,页面首次加载时会把posts数据渲染成静态HTML。客户端的动态更新是通过JavaScript直接操作DOM元素,而不是修改Jinja模板(模板已经在服务器处理完毕)。
  2. 定时拉取逻辑:使用setTimeout在每次请求完成后调度下一次更新,比setInterval更可靠——如果某次请求耗时超过5秒,setInterval会导致请求堆积,而setTimeout会等待当前请求完成后再启动下一次。
  3. 数据格式一致性:前后端必须约定好JSON结构,前端期望data.posts是数组,后端就必须返回包含posts字段的JSON对象。
  4. 无刷新表单提交:通过preventDefault()阻止表单默认提交行为,改用fetch发送POST请求,提交成功后重置表单并立即更新帖子列表,提升用户体验。

内容的提问来源于stack exchange,提问作者Ender Bender

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 06:17:05