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

Flask项目中Jinja模板调用Python函数的传参及触发问题

问题根源与解决方案

你遇到的核心问题是:Jinja模板是服务器端渲染引擎,当你在onclick里写{{ user_approve(user.id) }}时,模板渲染阶段就会直接执行这个Python函数,而不是等按钮点击时才触发——这就是为什么页面加载后函数就被调用了。

下面是两种可行的解决方式:


方法1:使用表单提交(无JS,简单直接)

把每个操作按钮包裹在独立表单里,通过提交表单触发后端路由,将用户ID通过路由参数或隐藏字段传递:

模板修改(user_approval.html)

<tbody>
    {% for user in users.items %}
        <tr>
            <td>{{ user.a_name }}</td>
            <td>{{ user.a_address }}</td>
            <td>{{ user.a_dob }}</td>
            <td>{{ user.a_email }}</td>
            <td>
                <form method="POST" action="{{ url_for('approve_user', user_id=user.id) }}">
                    <button type="submit" class="btn btn-success">Approve</button>
                </form>
            </td>
            <td>
                <form method="POST" action="{{ url_for('deny_user', user_id=user.id) }}">
                    <button type="submit" class="btn btn-danger">Deny</button>
                </form>
            </td>
        </tr>
    {% endfor %}
</tbody>

Flask后端路由

@app.route('/approve/<int:user_id>', methods=['POST'])
def approve_user(user_id):
    # 执行审批逻辑:更新用户状态
    user = User.query.get_or_404(user_id)
    user.is_approved = True
    db.session.commit()
    return redirect(url_for('user_approval'))  # 跳回审批页面

@app.route('/deny/<int:user_id>', methods=['POST'])
def deny_user(user_id):
    # 执行拒绝逻辑
    user = User.query.get_or_404(user_id)
    user.is_approved = False
    db.session.commit()
    return redirect(url_for('user_approval'))

方法2:AJAX异步请求(无刷新体验)

如果想要页面不刷新完成操作,用JavaScript发送异步请求:

模板修改

<tbody>
    {% for user in users.items %}
        <tr>
            <td>{{ user.a_name }}</td>
            <td>{{ user.a_address }}</td>
            <td>{{ user.a_dob }}</td>
            <td>{{ user.a_email }}</td>
            <td>
                <button onclick="handleApproval({{ user.id }}, true)" class="btn btn-success">Approve</button>
            </td>
            <td>
                <button onclick="handleApproval({{ user.id }}, false)" class="btn btn-danger">Deny</button>
            </td>
        </tr>
    {% endfor %}
</tbody>

<script>
function handleApproval(userId, isApproved) {
    const url = isApproved ? '/approve/' + userId : '/deny/' + userId;
    fetch(url, {
        method: 'POST',
        headers: {
            'X-CSRFToken': '{{ csrf_token() }}'  // 启用Flask-WTF的CSRF保护时必须添加
        }
    }).then(response => {
        if (response.ok) {
            // 操作成功后移除当前行或更新状态
            event.target.closest('tr').remove();
        }
    });
}
</script>

Flask后端路由(返回JSON)

from flask import jsonify

@app.route('/approve/<int:user_id>', methods=['POST'])
def approve_user(user_id):
    user = User.query.get_or_404(user_id)
    user.is_approved = True
    db.session.commit()
    return jsonify({'success': True})

@app.route('/deny/<int:user_id>', methods=['POST'])
def deny_user(user_id):
    user = User.query.get_or_404(user_id)
    user.is_approved = False
    db.session.commit()
    return jsonify({'success': True})

额外注意点

  • 不要在循环中使用重复的id(比如你之前的approve-user-btn),这会导致DOM元素ID冲突,可改为动态ID如approve-btn-{{ user.id }},或者直接去掉ID。
  • 如果使用Flask-WTF,确保CSRF令牌正确传递,避免403权限错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 22:10:28