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

Flask路由中HTML下拉列表传参引发UnboundLocalError问题

解决 Flask 中 UnboundLocalError 及表单提交、绘图的问题

看起来你遇到的UnboundLocalError主要是因为变量在某些分支下没有被赋值就尝试返回/使用,再加上表单设计和绘图流程的小问题,咱们一步步来修复:

1. 核心错误:未赋值的变量

问题分析

  • 在testt1()、testt2()和regrplot()函数里,你只有在POST请求时才会给x1/y1赋值,但如果是GET请求(比如用户直接访问这些路由),或者选中的字段不在任何一个xxx_fields列表里,这些变量就根本没被定义,直接返回/使用自然会报错。
  • 另外regrplot()里你把Reg_df的定义注释掉了,后面直接用Reg_df也会报未定义错误。

修复方案

  • 给变量设置默认值,或者确保所有分支都覆盖到赋值逻辑,同时处理异常情况;
  • 取消Reg_df的注释,确保合并后的DataFrame正确生成。

2. 表单设计问题:两个独立表单导致参数不全

问题分析

你现在把两个下拉框放在两个独立的<form>里,点击提交按钮时,只会提交第二个表单的df_variable2参数,第一个下拉框的df_variable1根本不会被传到后端,导致regrplot()里拿不到x轴的变量。

修复方案

把两个下拉框合并到同一个表单里,提交按钮放在这个表单内部,这样点击提交时两个参数都会被发送。

3. 绘图与静态资源的问题

问题分析

  • Flask默认从static文件夹读取静态资源,你直接把图片保存到根目录,前端html无法正确加载;
  • Seaborn依赖Matplotlib,在Flask这类非交互式环境下,需要设置Matplotlib使用非交互式后端,否则可能会有渲染错误;
  • 绘图后需要关闭Matplotlib的画布,避免内存泄漏。

完整修复后的代码

修改后的 dropdown.html

<body>
<form name="reg_form" action="/regrplot" method="POST">
    <fieldset>
        <legend>Table Variable 1 (X轴)</legend>
        <p>
            <label>Select</label>
            <select name="df_variable1">
                {% for each in dropdown_fields %}
                <option value="{{each}}">{{each}}</option>
                {% endfor %}
            </select>
        </p>
    </fieldset>
    <fieldset>
        <legend>Table Variable 2 (Y轴)</legend>
        <p>
            <label>Select</label>
            <select name="df_variable2">
                {% for each in dropdown_fields %}
                <option value="{{each}}">{{each}}</option>
                {% endfor %}
            </select>
        </p>
    </fieldset>
    <input type="submit" class="btn btn-default" value="生成回归图">
</form>
</body>

修改后的 app.py

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from flask import Flask, render_template, request

# 先设置Matplotlib非交互式后端,避免Flask环境下的渲染问题
plt.switch_backend('Agg')

app = Flask(__name__)

# 注意:这里假设你已经正确加载了book_data、censusLoad的DataFrame
# 修正获取列名的方式:应该取DataFrame的columns,而不是DataFrame本身
book_fields = list(book_data.df_yearbook.columns)
census1_fields = list(censusLoad.df_full1.columns)
census2_fields = list(censusLoad.df_full2.columns)
dropdown_fields = book_fields + census1_fields + census2_fields

@app.route("/dropdown")
def dropdownList():
    return render_template('dropdown.html', dropdown_fields=dropdown_fields)

@app.route("/regrplot", methods=['GET','POST'])
def regrplot():
    # 初始化默认值,避免未赋值错误
    x_df = None
    y_df = None
    df_variable1 = None
    df_variable2 = None
    
    if request.method == 'POST':
        df_variable1 = request.form.get('df_variable1')
        df_variable2 = request.form.get('df_variable2')
        
        # 匹配X轴对应的DataFrame
        if df_variable1 in book_fields:
            x_df = book_data.df_yearbook
        elif df_variable1 in census1_fields:
            x_df = censusLoad.df_full1
        elif df_variable1 in census2_fields:
            x_df = censusLoad.df_full2
        
        # 匹配Y轴对应的DataFrame
        if df_variable2 in book_fields:
            y_df = book_data.df_yearbook
        elif df_variable2 in census1_fields:
            y_df = censusLoad.df_full1
        elif df_variable2 in census2_fields:
            y_df = censusLoad.df_full2
        
        # 检查DataFrame是否获取成功,以及是否有year列
        if x_df is not None and y_df is not None and 'year' in x_df.columns and 'year' in y_df.columns:
            # 按year合并DataFrame
            Reg_df = x_df.merge(y_df, how="inner", on='year')
            # 检查选中的列是否存在于合并后的DataFrame
            if df_variable1 in Reg_df.columns and df_variable2 in Reg_df.columns:
                # 生成回归图
                plt.figure(figsize=(10,6))
                sns.regplot(x=df_variable1, y=df_variable2, data=Reg_df)
                # 保存到static文件夹,方便前端访问
                plt.savefig('static/regrplot.png')
                plt.close()  # 关闭画布,释放内存
    
    # 不管POST还是GET,都返回绘图页面(如果有图就显示,没有就显示空白)
    return render_template("regression.html")

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

修改后的 regression.html

<!DOCTYPE HTML>
<html lang="en">
<head>
    <title>回归图结果</title>
    <meta charset="UTF-8" />
</head>
<body>
    <!-- 使用Flask的url_for生成静态资源路径,确保正确加载 -->
    <img src="{{ url_for('static', filename='regrplot.png') }}" alt="回归图">
</body>
</html>

额外注意事项

  • 确保book_data和censusLoad的DataFrame已经正确加载,并且包含year列;
  • 如果你的DataFrame列名有重复(比如不同DataFrame有相同列名),可以考虑在合并时给列名加前缀,避免混淆;
  • 可以在后端增加错误提示,比如当用户选择的字段不存在或者合并失败时,在前端显示提示信息,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:35:11