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

Flask路由中创建UserRelationship关联对象遇JSON序列化错误

解决Flask中TypeError: Object of type UserRelationship is not JSON serializable错误

这个错误的核心原因很明确:你在路由里调用flash(current_user.follows)时,current_user.follows是UserRelationship对象的列表,而Flask的flash函数会将消息存入用户会话(session),会话中的数据必须能被序列化为JSON格式——但SQLAlchemy的ORM模型对象默认不支持这种序列化。

为什么Python Shell里没问题?

在Shell中直接打印或操作current_user.follows时,不需要将对象序列化后存入session,所以不会触发这个错误;但路由里的flash会把内容持久化到session,这就要求内容必须是JSON可序列化的类型(比如字符串、列表、字典等)。


快速修复:修改flash的内容

你不需要直接把ORM对象传给flash,改成传递用户可读的字符串消息即可,比如:

# 替换原来的flash(current_user.follows)
flash(f"Successfully followed {follow_target.username}!")
# 或者如果需要显示关注列表的信息
flash(f"You now follow {len(current_user.follows)} users")

模型设计的潜在问题(重要)

另外,你的UserRelationship模型设计存在逻辑缺陷:目前只有follows_id作为主键,这意味着一个用户只能关注一个其他用户,这显然不符合“关注”功能的实际需求。

正确的多对多关注关系中间表应该包含两个外键作为复合主键:

  • follower_id:发起关注的用户ID(即当前用户)
  • followed_id:被关注的用户ID

修改后的模型示例:

class UserRelationship(db.Model):
    follower_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
    followed_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
    bank = db.Column(db.String(100))
    
    # 定义关系:关联到发起关注的用户
    follower = db.relationship('User', foreign_keys=[follower_id], backref=db.backref('following', lazy='dynamic'))
    # 定义关系:关联到被关注的用户
    followed = db.relationship('User', foreign_keys=[followed_id], backref=db.backref('followers', lazy='dynamic'))

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    # 这里不需要额外定义follows关系,上面的backref已经自动生成了following和followers属性

对应的路由代码也需要调整,创建UserRelationship时要指定两个用户:

new_follow = UserRelationship(
    follower=current_user,
    followed=follow_target,
    bank='1000'
)
db.session.add(new_follow)
db.session.commit()

如果你确实需要序列化ORM对象(不推荐用于flash)

如果一定要在session中传递模型数据,可以给UserRelationship添加一个序列化方法,将对象转换为字典:

class UserRelationship(db.Model):
    # ... 原有字段和关系 ...
    def to_dict(self):
        return {
            'follower_id': self.follower_id,
            'followed_id': self.followed_id,
            'bank': self.bank,
            'followed_username': self.followed.username
        }

然后在flash时转换为字典列表:

flash([rel.to_dict() for rel in current_user.following])

不过还是强烈建议不要用flash传递复杂数据,它的设计初衷是显示简短的提示消息,复杂数据应该用其他方式(比如模板上下文)传递。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:44:38