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

FastAPI中Pydantic接收参数后返回全null值的问题求助

问题分析与修复方案

问题现象

提交包含Name、Surname、email、password的请求体后,接口返回所有字段为null。

核心问题

  1. 字段命名不匹配:schemas.Student使用大驼峰字段名(Name、Surname),但SQLAlchemy模型(models.Students)通常采用小驼峰/下划线命名(如name、surname),导致ORM模式无法正确映射字段,最终返回null。
  2. 返回逻辑错误:create_user中直接返回student.dict()且未刷新数据库对象;try-except直接返回异常对象,不符合响应模型要求。
  3. 路由路径错误:update_student的路径缺少分隔斜杠,应为/update_student/{id}而非/update_student{id}。

修复步骤

1. 统一字段命名(推荐方案)

修改schemas.py,将字段改为小驼峰,与SQLAlchemy模型保持一致:

from datetime import datetime
from pydantic import BaseModel, EmailStr
from typing import Optional


class Student(BaseModel):
    name: Optional[str]
    surname: Optional[str]
    email: Optional[EmailStr]
    password: Optional[str]
    
    class Config:
        orm_mode = True

同时确保models.Students的字段名也是name、surname等小驼峰格式。

2. 修复create_user接口逻辑

@router.post("/create_student", status_code=status.HTTP_201_CREATED, response_model=schemas.Student)
async def create_user(student: schemas.Student, db: Session = Depends(get_db)):
    if not student.password:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Password is required")
    
    # 哈希密码
    hashed_password = utils.hash(student.password)
    student_data = student.dict()
    student_data["password"] = hashed_password
    
    # 创建数据库对象
    new_student = models.Students(**student_data)   
    db.add(new_student)
    db.commit()
    # 刷新对象以获取数据库生成的字段(如id)
    db.refresh(new_student)
    
    return new_student
  • 移除错误的try-except直接返回异常的逻辑,改为主动校验必填字段并抛出标准HTTP异常。
  • 使用db.refresh()获取数据库中最新的对象数据,确保返回正确值。
  • 直接返回ORM对象,FastAPI会通过response_model自动序列化。

3. 修复update_student路由路径与逻辑

@router.put('/update_student/{id}', response_model=schemas.Student)
async def update_student(id: int, student: schemas.Student, db: Session = Depends(get_db)):
    db_student = db.query(models.Students).filter(models.Students.id == id).first()
    if not db_student:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Student not found")
    
    # 仅更新用户提交的非空字段
    update_data = student.dict(exclude_unset=True)
    if update_data.get("password"):
        update_data["password"] = utils.hash(update_data["password"])
    
    for key, value in update_data.items():
        setattr(db_student, key, value)
    
    db.commit()
    db.refresh(db_student)
    return db_student
  • 修正路由路径,添加/分隔符。
  • 先查询学生是否存在,避免无意义的更新操作。
  • 使用exclude_unset=True仅更新用户提交的字段,避免覆盖已有非空值。
  • 哈希更新的密码(如果提交了)。

4. 调整请求体格式

如果使用了小驼峰字段名,请求体应改为:

{
  "name": "string",
  "surname": "string",
  "email": "user@example.com",
  "password": "string"
}

可选:保留大驼峰请求字段(字段别名方案)

如果需要保持请求体的大驼峰格式,可以给schemas.Student字段添加别名:

from pydantic import BaseModel, EmailStr, Field
from typing import Optional


class Student(BaseModel):
    name: Optional[str] = Field(alias="Name")
    surname: Optional[str] = Field(alias="Surname")
    email: Optional[EmailStr] = Field(alias="email")
    password: Optional[str] = Field(alias="password")
    
    class Config:
        orm_mode = True
        allow_population_by_field_name = True

这样既可以接收大驼峰的JSON键,又能与小驼峰的数据库模型字段映射。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 04:57:52