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

Flask+PostgreSQL REST API重构后遇404错误,求解决方案

解决Flask通用API路由的404与功能问题

嘿,我来帮你梳理下重构代码里的问题,几个小调整就能让你的通用API正常工作啦!

主要问题与修改点:

1. 路由定义错误(直接导致404)

你用了${table_name}这种非Flask规范的路由变量写法,Flask要求路由变量用<变量名>的格式。另外你的访问路径/api/stat_data是把表别名放在URL路径里,但原重构代码却用查询参数来获取,逻辑完全不匹配。

修改方案:把路由改成接收路径变量,对应你dico里的键:

@app.route('/api/<table_alias>', methods=("POST", "GET"))
def get_table_json(table_alias):
    # 后续用table_alias去匹配dico里的真实表名

2. SQL查询字符串格式化错误

get_table函数里的SQL语句没有正确替换变量,${table_name}是模板语法,Python根本不识别,要改用f-string或者.format()来处理变量替换:

def get_table(table_name):
    # 用f-string替换变量,注意PostgreSQL的表名如果有大小写需要加双引号
    query = f'select * from "{table_name}"'
    return pd.read_sql_query(query, con=engine)

3. 变量名不匹配导致报错

你在函数里把查询结果赋值给了data_generique,但return的时候写的是df_generique.to_json(),这会直接抛出NameError,必须统一变量名:

data_generique = get_table(dico[table_alias])
return data_generique.to_json()

4. 参数逻辑与异常处理优化

既然用了路径变量,就不需要再用request.args.get('table')了,直接用路由传入的table_alias去匹配你的dico映射即可。另外最好加个别名合法性校验,防止传入不存在的别名导致KeyError:

def get_table_json(table_alias):
    if table_alias not in dico:
        return {"error": "无效的表别名"}, 400
    # 再加个异常捕获,避免数据库查询报错直接崩掉服务
    try:
        data_generique = get_table(dico[table_alias])
        return data_generique.to_json()
    except Exception as e:
        return {"error": f"查询失败:{str(e)}"}, 500

修改后的完整代码:

from flask import Flask, request
import pandas as pd
# 假设你的engine已经正确初始化(比如用sqlalchemy创建)
# engine = create_engine(...)

app = Flask(__name__)

dico = {
    'stat_data': "srcstatistiquedata",
    'stat_suppr': "srcstatistiquesuppression",
    'en_tete': "srcentete"
}

def get_table(table_name):
    query = f'select * from "{table_name}"'
    return pd.read_sql_query(query, con=engine)

@app.route('/api/<table_alias>', methods=("POST", "GET"))
def get_table_json(table_alias):
    if table_alias not in dico:
        return {"error": "无效的表别名"}, 400
    try:
        data_generique = get_table(dico[table_alias])
        return data_generique.to_json()
    except Exception as e:
        return {"error": f"查询失败:{str(e)}"}, 500

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

补充说明:

  • 现在你访问http://127.0.0.1:5000/api/stat_data就能拿到srcstatistiquedata表的数据了,其他别名(stat_suppr、en_tete)同理。
  • 关于SQL注入:因为你用了dico做白名单映射,只允许传入预定义的别名,不会直接把用户输入拼到SQL里,所以相对安全。如果直接用用户输入作为表名,会有很大的注入风险,一定要避免。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 12:39:05