Flask应用中User模型id=19时is_admin未正确赋值的问题
问题分析
核心问题是:在__init__方法中调用set_user时,数据库还未为用户分配自增的id值。此时self.id为None,self.id == 19的判断永远不成立,导致即使最终数据库生成的id是19,is_admin也不会被设为True,反而因走else分支将is_user设为True。
另外原set_user存在逻辑漏洞:当id=19时,仅设置is_admin=True,未显式将is_user设为False,不符合需求中的互斥逻辑。
解决方案
方案1:使用SQLAlchemyafter_insert事件监听
利用SQLAlchemy事件系统,在用户数据插入数据库、获取实际id后再执行权限设置:
from sqlalchemy import event from datetime import datetime class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(255), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) password = db.Column(db.String(255), nullable=False) is_user = db.Column(db.Boolean, default=False, nullable=False) is_admin = db.Column(db.Boolean, default=False, nullable=False) books = db.relationship('Book', backref="users") journals = db.relationship('Journal', backref="users") created_at = db.Column(db.DateTime, default=datetime.now) updated_at = db.Column(db.DateTime, onupdate=datetime.now) def set_user(self): if self.id == 19: self.is_admin = True self.is_user = False else: self.is_user = True self.is_admin = False def to_dict(self): return dict(id=self.id, username=self.username, email=self.email) # 注册插入后事件,同步权限设置到数据库 @event.listens_for(User, 'after_insert') def sync_user_permission(mapper, connection, target): target.set_user() connection.execute( User.__table__.update() .where(User.id == target.id) .values(is_admin=target.is_admin, is_user=target.is_user) )
方案2:手动指定id场景的处理(允许手动设置主键时)
如果业务允许手动指定用户id,创建时传入id=19,此时__init__可直接获取id值:
class User(db.Model): # 字段定义与方案1一致 def set_user(self): if self.id == 19: self.is_admin = True self.is_user = False else: self.is_user = True self.is_admin = False def __init__(self, **kwargs): super().__init__(**kwargs) self.set_user() # 创建id=19的用户时手动传入id user = User(id=19, username="test19", email="test19@email.com", password="your_password") db.session.add(user) db.session.commit()
关键修正点
- 原
created_at的default=datetime.now()会导致所有用户创建时间为服务器启动时间,需改为default=datetime.now(传递函数引用,每次创建对象时生成当前时间)。 - 权限逻辑需确保互斥:id=19时
is_admin=True且is_user=False,其他情况反之,避免权限状态混乱。
验证结果
使用方案1创建id=19的用户后,输出将符合预期:
{ "message": "User created", "user": { "email": "test19@email.com", "id": 19, "is_admin": true, "is_user": false, "username": "test19" } }
内容的提问来源于stack exchange,提问作者Joboa
相关产品推荐
相关产品推荐

