首页 > 解决方案 > 如何删除具有指定角色的所有用户

问题描述

这些是我的用户和角色模型:

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    firstname = db.Column(db.String(100), nullable=False, server_default='')
    lastname = db.Column(db.String(100), nullable=False, server_default='')
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(80), unique=True, nullable=False)
    password = db.Column(db.String(200), nullable=False)
    answers = db.relationship('Answer', backref="examinee", lazy=True)
    date_created = db.Column(db.DateTime, default=datetime.utcnow)
    active = db.Column('is_active', db.Boolean(), nullable=False, server_default='0')
    roles = db.relationship('Role', secondary='user_roles', backref=db.backref('users', lazy='dynamic'))

class Role(db.Model, RoleMixin):
    id = db.Column(db.Integer(), primary_key=True, autoincrement=True)
    name = db.Column(db.String(50), unique=True)
    description = db.Column(db.String(255))

class UserRoles(db.Model):
    id = db.Column(db.Integer(), primary_key=True, autoincrement=True)
    user_id = db.Column(db.Integer(), db.ForeignKey('user.id', ondelete='CASCADE'))
    role_id = db.Column(db.Integer(), db.ForeignKey('role.id', ondelete='CASCADE'))
    UniqueConstraint('user_id', 'role_id', name='user_role_uniqueness')

如何删除具有特定角色(例如“学生”)的所有用户?

我尝试了以下无效的代码段:

@app.route('/removeAllStudentUsers', methods=['GET', 'POST'])
def remove_all_student_users():
    default_role_name = "student"
    default_role = Role.query.filter(Role.name == default_role_name).first()
    User.query.filter().delete(and_(User.roles.contains(default_role), func.count(User.roles) == 1)) # this line causes the error
    db.session.commit()
    return redirect(url_for('users'))

上面的代码会导致这个错误:

sqlalchemy.exc.ArgumentError:会话同步的有效策略是“评估”、“获取”、“假”

标签: pythonflasksqlalchemyflask-sqlalchemy

解决方案


您尝试实现这一目标存在多个问题,包括您可能需要 group by 以检查角色计数的事实。

我将执行以下操作:

_ = (
    User.query
    .filter(User.roles.any(Role.name == default_role_name))   # 1
    .filter(~User.roles.any(Role.name != default_role_name))  # 2
    .delete(synchronize_session=False)  # 3
)

在哪里:

  1. 确保只返回User具有给定角色的人
  2. 确保排除User还有其他角色的人(这是您尝试解决的问题func.count
  3. 这是您遇到的错误的解决方案。

推荐阅读