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
相关产品推荐
相关产品推荐

