FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
FastAPI + Flask 混合部署指南是一项面向实际任务的技能,主要用于当你需要同时运行 FastAPI 后端 API 和 Flask 前端服务时,需要注意以下关键问题;核心踩坑与解决方案;
问题 : 前端通过 Fl。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。从功能定位来看,该技能强调把分散的操作要求整理成清晰、可复用的处理流程,使用户能够围绕既定目标快速准备输入、选择执行方式并获得结构化结果。实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;
若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。该技能适合用于一次性任务,也可以接入自动化工作流,与其他技能或上层代理配合完成更完整的业务链路;在组合使用时,应明确每一步的输入输出关系,并避免不同步骤之间出现参数冲突。
当你需要同时运行 FastAPI 后端 API 和 Flask 前端服务时,需要注意以下关键问题。
┌─────────────────────────────────────────┐
│ 用户浏览器 │
└─────────────────┬───────────────────────┘
│ :15000
▼
┌─────────────────────────────────────────┐
│ Flask (端口 15000) │
│ - 静态页面 │
│ - API 代理 → FastAPI │
└─────────────────┬───────────────────────┘
│ 内部调用
▼
┌─────────────────────────────────────────┐
│ FastAPI (端口 18000) │
│ - REST API │
│ - 业务逻辑 │
└─────────────────────────────────────────┘
问题: 路由定义在 if __name__ == "__main__": 之后,导致路由未被注册。
错误示例:
from fastapi import FastAPI
app = FastAPI()
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=18000)
# ❌ 路由定义在 main 之后,不会被加载!
@app.get("/api/hello")
def hello():
return {"message": "Hello"}
正确示例:
from fastapi import FastAPI
app = FastAPI()
# ✅ 路由定义在 main 之前
@app.get("/api/hello")
def hello():
return {"message": "Hello"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=18000)
问题: 前端通过 Flask (15000端口) 访问,但 API 在 FastAPI (18000端口),存在跨域问题。
解决方案: 在 Flask 中添加 API 代理。
from flask import Flask, request, Response
import requests
app = Flask(__name__)
FASTAPI_BASE = "http://localhost:18000"
# 代理 GET 请求
@app.route("/api/", methods=["GET"])
def proxy_get(path):
resp = requests.get(f"{FASTAPI_BASE}/api/{path}", params=request.args)
return Response(resp.content, status=resp.status_code,
headers={"Content-Type": "application/json"})
# 代理 POST 请求
@app.route("/api/", methods=["POST"])
def proxy_post(path):
resp = requests.post(f"{FASTAPI_BASE}/api/{path}",
json=request.get_json())
return Response(resp.content, status=resp.status_code,
headers={"Content-Type": "application/json"})
# 代理 DELETE 请求
@app.route("/api/", methods=["DELETE"])
def proxy_delete(path):
resp = requests.delete(f"{FASTAPI_BASE}/api/{path}")
return Response(resp.content, status=resp.status_code,
headers={"Content-Type": "application/json"})
# 代理 PUT 请求
@app.route("/api/", methods=["PUT"])
def proxy_put(path):
resp = requests.put(f"{FASTAPI_BASE}/api/{path}",
json=request.get_json())
return Response(resp.content, status=resp.status_code,
headers={"Content-Type": "application/json"})
问题: 新增的模型类在路由文件中未导入,导致 NameError。
解决方案: 确保所有使用的类都已导入。
# models.py
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
from database import Base
class Trajectory(Base):
__tablename__ = "trajectories"
id = Column(Integer, primary_key=True)
# ...
class Annotation(Base):
__tablename__ = "annotations"
id = Column(Integer, primary_key=True)
trajectory_id = Column(Integer, ForeignKey("trajectories.id"))
# ...
# main.py (FastAPI)
from models import Trajectory, Annotation, Response, Prompt # ✅ 全部导入
@app.delete("/api/trajectories/{trajectory_id}")
def delete_trajectory(trajectory_id: int, db: Session = Depends(get_db)):
# 现在可以正确访问所有模型
annotation = db.query(Annotation).filter(
Annotation.trajectory_id == trajectory_id
).first()
# ...
问题: 删除主记录时,关联的外键记录如何处理?
方案 A: 数据库级联删除(推荐)
class Trajectory(Base):
__tablename__ = "trajectories"
id = Column(Integer, primary_key=True)
annotations = relationship("Annotation", cascade="all, delete-orphan")
方案 B: 手动删除关联记录
@app.delete("/api/trajectories/{trajectory_id}")
def delete_trajectory(trajectory_id: int, db: Session = Depends(get_db)):
# 先删除关联的 annotations
db.query(Annotation).filter(
Annotation.trajectory_id == trajectory_id
).delete()
# 再删除主记录
trajectory = db.query(Trajectory).filter(
Trajectory.id == trajectory_id
).first()
if trajectory:
db.delete(trajectory)
db.commit()
return {"status": "deleted"}
#!/bin/bash # 启动 FastAPI 后端 (后台运行) cd /app python -m uvicorn api:app --host 0.0.0.0 --port 18000 & FASTAPI_PID=$! # 启动 Flask 前端 python frontend.py # 清理 kill $FASTAPI_PID 2>/dev/null
version: '3.8'
services:
api:
build: .
command: python -m uvicorn api:app --host 0.0.0.0 --port 18000
ports:
- "18000:18000"
web:
build: .
command: python frontend.py
ports:
- "15000:15000"
depends_on:
- api
environment:
- FASTAPI_URL=http://api:18000
if __name__ == "__main__": 之前定义所有路由wphu@gpu506.aibee.cn:/data/algorithm/user/wphu/OmniMLLM/preference-align