如何在FastAPI注册接口中同时上传文件与JSON格式学校列表数据?
FastAPI form-data 多学校信息列表传递最优方案
方案一:通过JSON字符串传递学校列表(推荐)
这种方式实现简单,前后端代码量少,只需将学校列表转为JSON字符串放入form-data字段,后端结合Json类型解析为Pydantic模型列表。
1. 修正用户信息模型错误
原模型as_form方法存在参数名错误,修正后:
from pydantic import BaseModel from fastapi import Form, Depends, UploadFile, File, status from sqlalchemy.orm import Session from typing import List, Annotated from pydantic import Json class User(BaseModel): name: str password: str email: str @classmethod def as_form(cls, name: str = Form(...), password: str = Form(...), email: str = Form(...)) -> 'User': return cls(name=name, password=password, email=email)
2. 学校信息模型保持不变
class School(BaseModel): school: str country: str
3. 接口定义修改
用Annotated[List[School], Form()]结合Json解析JSON字符串为学校列表:
@router.post("/signup", status_code=status.HTTP_201_CREATED) async def signup( schools: Annotated[List[School], Form()], user: User = Depends(User.as_form), file: UploadFile = File(), session: Session = Depends(db.session) ): # 后续业务逻辑:保存用户、学校信息、处理上传文件等 return { "user": user.dict(), "schools": [s.dict() for s in schools], "uploaded_file": file.filename }
前端传递要求
form-data需包含以下字段:
name/password/email:普通字符串类型schools:值为学校列表的JSON字符串,例如:[{"school":"清华大学","country":"中国"},{"school":"MIT","country":"美国"}]file:待上传的文件
方案二:通过多字段批量传递(适配前端无法生成JSON的场景)
如果前端无法处理JSON字符串,可通过结构化命名的多字段传递学校信息,后端自定义依赖解析为模型列表。
1. 自定义依赖项解析学校列表
from fastapi import Request async def get_schools_from_form(request: Request) -> List[School]: form_data = await request.form() schools = [] # 提取所有学校索引 school_indexes = set() for key in form_data.keys(): if key.startswith("schools-"): parts = key.split("-") if len(parts) >= 3: school_indexes.add(parts[1]) # 按索引解析每所学校的信息 for idx in school_indexes: school_name = form_data.get(f"schools-{idx}-school") country = form_data.get(f"schools-{idx}-country") if school_name and country: schools.append(School(school=school_name, country=country)) return schools
2. 接口使用自定义依赖
@router.post("/signup", status_code=status.HTTP_201_CREATED) async def signup( schools: List[School] = Depends(get_schools_from_form), user: User = Depends(User.as_form), file: UploadFile = File(), session: Session = Depends(db.session) ): # 后续业务逻辑 return { "user": user.dict(), "schools": [s.dict() for s in schools], "uploaded_file": file.filename }
前端传递要求
form-data需包含以下类型字段:
name/password/email:普通字符串类型- 多组学校字段:如
schools-0-school(第一所学校名称)、schools-0-country(第一所学校国家)、schools-1-school(第二所学校名称)等 file:待上传的文件
方案对比
- 方案一:代码简洁,前后端实现成本低,是最优选择,优先采用。
- 方案二:适配前端受限场景,但字段命名需严格遵循规则,代码相对繁琐。
内容的提问来源于stack exchange,提问作者giwony
相关产品推荐
相关产品推荐

