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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 18:05:20