核心内容摘要
独家猛料!“吃瓜网黑料”让你秒变朋友圈焦点!
你疑惑的这两段代码detail接口的mappings()查询、Videos模型类本质上是「定义」和「查询实现」的关系本身没有逻辑冲突但存在「字段约束不匹配」和「查询方法兼容性」两个关键小坑这也是为什么数据库有数据查询后却取不到显示None的核心原因。
我们先拆解两者的关联与差异再给出针对性修正。
先明确两段代码的核心关系class Videos(SQLModel, tableTrue)是数据库表的「抽象定义」规定了表的字段名、字段类型、约束必填/主键等相当于给数据库表和 Python 代码之间搭了一座桥。
session.execute(sql).mappings().first()是查询数据库的「实现方式」目的是从数据库中取出数据映射成 Python 可操作的对象本应和Videos模型类匹配但有两个坑导致映射失败。
关键差异/问题导致数据查询后显示None问题1Videos模型类的字段约束过于严格与mappings()兼容性差你的Videos模型中除了videoid是int|None可选其他字段videotitle、filename、keyword等都是必填类型无|None、无默认值但mappings()返回的是「松散的 RowMapping 映射对象」不遵守Videos模型的必填约束若数据库中某个字段比如keyword、reference是NULL上传时未赋值而模型类中定义为str必填mappings()映射时无法满足「必填 str」的约束会直接将该字段置为None甚至连带影响其他非 NULL 字段的映射比如filename、summary导致你打印时显示None。
而scalars()返回的是Videos模型实例会严格遵守模型类的字段定义自动处理「数据库 NULL 值」和「模型字段类型」的转换兼容性更好。
问题2Videos模型缺少「自增属性」与数据库自增字段不匹配你的videoid定义videoid:int|NoneField(defaultNone,primary_keyTrue)虽然数据库中videoid大概率设置了「自增主键」但模型类中缺少自增配置sa_column_kwargs{autoincrement: True}导致模型类和数据库的「自增属性」不匹配mappings()映射时无法正确识别videoid的取值间接影响其他字段的查询结果映射出现「数据库有值查询后为None」的现象。
问题3mappings()vsscalars()查询结果的本质差异核心这是最关键的一点两者返回的结果完全不同直接决定了能否取到数据查询方法返回结果类型与Videos模型的关联取值稳定性mappings().first()SQLAlchemyRowMapping只读字典类似物无直接关联仅做「列名-值」简单映射差容易丢失数据、出现Nonescalars().first()Videos模型实例严格遵守模型定义强关联自动处理字段类型转换高100% 保留模型字段数据简单说mappings()是「无差别映射」不管你的Videos模型怎么定义只按数据库返回的列名映射scalars()是「精准映射」只返回符合Videos模型定义的实例兼容性和稳定性远高于mappings()。
针对性修正两步搞定确保数据能正常取出步骤1修正Videos模型类匹配数据库放宽合理约束fromsqlmodelimportSQLModel,FieldfromdatetimeimportdatetimeclassVideos(SQLModel,tableTrue):# 修正1补全自增属性与数据库自增主键匹配videoid:int|NoneField(defaultNone,primary_keyTrue,sa_column_kwargs{autoincrement:True}# 新增开启自增)# 修正2核心字段必须有值保留必填非核心字段加可选约束|None兼容数据库 NULLvideotitle:strfilename:strduration:intcoursename:strcontent:strsummary:str# 非核心字段允许为 None兼容数据库 NULL避免映射失败keyword:str|NoneField(defaultNone)reference:str|NoneField(defaultNone)xmindjson:str|NoneField(defaultNone)examjson:str|NoneField(defaultNone)createtime:datetime步骤2修正detail接口查询方法改用scalars()转字典确保模板取值这是解决「None问题」的核心直接替换你现有detail接口fromfastapiimportHTTPException# 确保已导入app.get(/detail/{videoid})defdetail(request:Request,videoid:int):withSession(engine)assession:sqlselect(Videos).where(Videos.videoidvideoid)# 修正改用 scalars() 获取 Videos 模型实例而非 mappings()video_instancesession.execute(sql).scalars().first()ifnotvideo_instance:raiseHTTPException(status_code404,detail该视频记录不存在)# 模型实例转普通字典确保模板取值稳定videovideo_instance.dict()# 调试打印此时能看到真实数据不会是 Noneprint( 调试查询到的视频数据 )print(文件名,video.get(filename))print(
总结内容,video.get(summary))print(视频标题,video.get(videotitle))print()returntemplates.TemplateResponse(requestrequest,namedetail.html,context{video:video})
验证效果重启 FastAPI 服务CtrlC后重新运行代码访问http://
127.
0.
1:8000/detail/2查看控制台打印此时会显示数据库中的真实数据比如filename是你的视频文件名summary是你的
总结内容不会再是None模板页面中和会正常渲染出内容。
总结两段代码无本质逻辑冲突但存在「字段约束」和「查询方法兼容性」问题核心坑mappings()兼容性差无法处理模型必填约束与数据库 NULL 值的矛盾导致数据显示None关键解决模型类补全自增放宽非核心字段约束查询改用scalars()获取模型实例并转字典。
按这个方法修正后你的数据就能正常查询和显示了不会再出现「数据库有值查询后为 None」的现象。