FastAPI分页获取去重用户数据返回空值问题求助
问题分析与解决方案
你的问题出在查询语句和响应模型不匹配,以及去重逻辑的实现方式错误:
字段不匹配导致返回null
你写的select(distinct(User.first_name))只查询了first_name这一个字段,但响应模型UserBase要求返回last_name、email、active等完整用户字段。数据库没有返回这些字段的值,所以Pydantic只能将它们填充为null。去重逻辑不符合需求
如果你的目标是获取去重后的完整用户记录(每个唯一的first_name对应一条用户数据),仅查询distinct(User.first_name)无法实现——它只会返回去重后的名字列表,而非完整用户对象。
正确的实现方式
方案1:通用数据库兼容写法(子查询取唯一记录)
通过子查询先找到每个first_name对应的唯一标识(比如最早创建的用户ID),再关联原表获取完整用户数据:
from sqlalchemy import select, func from fastapi_pagination.ext.sqlalchemy import paginate @app.get('/users', response_model=Page[UserBase]) def get_users(db: Session = Depends(get_db)): # 子查询:按first_name分组,取每组中最小的用户ID(确保每个first_name仅保留一条记录) unique_user_ids = select(func.min(User.id)).group_by(User.first_name).subquery() # 查询完整用户数据,过滤出子查询中的ID query = select(User).where(User.id.in_(unique_user_ids)).order_by(User.created_at) return paginate(db, query)
方案2:PostgreSQL专属写法(DISTINCT ON)
如果你的数据库是PostgreSQL,可以用DISTINCT ON语法更简洁地实现按first_name去重,同时指定保留哪一条记录:
from sqlalchemy import select from fastapi_pagination.ext.sqlalchemy import paginate @app.get('/users', response_model=Page[UserBase]) def get_users(db: Session = Depends(get_db)): # 按first_name去重,保留每组中最早创建的记录 query = select(User).distinct(User.first_name).order_by(User.first_name, User.created_at) return paginate(db, query)
额外说明
- 原代码中
order_by(User.created_at)存在逻辑问题:因为你没有在查询中选择created_at字段,部分数据库会直接报错,即使不报错,排序逻辑也不可靠。 - 分页参数中的
pages显示为0是因为原查询返回的是单列数据,分页组件无法正确计算总页数,修复查询逻辑后即可正常显示。
内容的提问来源于stack exchange,提问作者cric
相关产品推荐
相关产品推荐

