Flask-SQLAlchemy查询单条/多条记录时BLOB字段返回类型不一致问题
问题原因
这个差异是SQLAlchemy会话缓存机制导致的,和get()、filter_by()两种查询方法本身的返回逻辑无关:
- 你先执行了
post.query.get()获取了置顶帖实例,手动对pin_post.text做了decode操作,把原本的bytes类型值改成了str类型,并且赋值回了实例属性。 - SQLAlchemy的会话(Session)会默认缓存已经查询过的模型实例,只要是同一个会话上下文中,后续查询命中同主键的实例时,会直接返回缓存里已经修改过的对象,不会重新从数据库读取字段做类型映射。
- 你后面用
filter_by().all()查询到的结果列表里,包含了前面已经修改过的置顶帖实例,这条记录的text已经是str类型,其他没有命中缓存的普通帖子,text字段依然是原生的bytes类型,你可以单独打印非置顶帖的text类型验证这一点。
解决方案
不要在查询中途直接修改模型实例的原生字段值,推荐通过模型属性封装统一的解码逻辑,一劳永逸解决类型混乱问题:
class post(db.Model): # 其余字段定义省略 text = db.Column(db.BLOB) # 新增只读属性,统一返回解码后的字符串 @property def decoded_text(self): if isinstance(self.text, bytes): return self.text.decode('utf-8') return self.text
后续所有查询场景下,直接调用实例.decoded_text就能拿到字符串类型的内容,不需要再手动做decode判断。
如果确实需要手动修改实例字段避免缓存影响,可以在修改后调用db.session.expunge(实例对象)将其从会话缓存中移除,不过该操作会额外增加数据库查询次数,不推荐常规场景使用。
内容的提问来源于stack exchange,提问作者Ajay Chahal
相关产品推荐
相关产品推荐

