Flask-Admin权限,用于添加具有特定角色的用户

问题描述 投票:0回答:2

我使用Flask-Admin和Flask-Security为我的Python应用程序实现管理面板。以下是UserRole的模型:

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

    def __str__(self):
        return self.name


class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(255), unique=True, index=True)
    password = db.Column(db.String(255))
    roles = db.relationship('Role', secondary=roles_users,
                            backref=db.backref('users', lazy='dynamic'))

    def __str__(self):
        return self.username

我为用户创建了一个sqla.ModelView,仅供角色为“admin”和“superadmin”的用户使用,因此这些用户可以使用此视图创建新用户。如何才能让只有角色“superadmin”的用户可以创建角色为“superadmin”和“admin”的用户?换句话说,我想指定哪些变体可用于具有不同角色的用户:https://imgur.com/a/GdhUS2Y

python flask flask-sqlalchemy roles flask-admin
2个回答
1
投票

要做到这一点,你必须自定义一些东西。

我建议如下:

在用户模型中添加此方法,以检查用户是否具有特定角色:

def has_role(self, role):
    # db is your database session. 
    query = db.query(Role).filter(Role.name == role).first()
    if query:
        if query.name in self.roles:
            return True
    return False

现在,您必须自定义用户尝试创建新用户时显示的角色。要实现这一点,您需要更改角色字段的定义。为此,您需要覆盖flask-admin scaffold_form()方法。

from flask_admin.contrib.sqla.fields import QuerySelectMultipleField
from flask_security import current_user
from flask_admin.form import Select2Widget
def scaffold_form(self):
    form_class = super(YourUserAdminClass, self).scaffold_form()
    role_filter = Role.name == Role.name if current_user.has_role('superadmin') else Role.name.notin_('superadmin', 'admin')
    form_class.roles = QuerySelectMultipleField(
            query_factory=lambda: self.session.query(Role).filter(role_filter),
            allow_blank,
            blank_text='Select Role',
            widget=Select2Widget(multiple=False) # change this to True if you allow multiple roles
        )

上面的代码将根据current_user的角色呈现带有角色的下拉列表(在过滤器中使用has_role()方法)


0
投票

虽然@shifloni的答案简明扼要地说明了我需要做什么,但根据我所观察到的,我认为这是不完整的。这是因为if current_user.has_role('superadmin')在应用程序初始化期间抛出错误,因为current_user仅在代码在请求上下文中执行时才可用。这对我有用:

class ViewForCreatingAdminAndOperators(sqla.ModelView):
    def _run_view(self, fn, *args, **kwargs):
        if current_user.has_role('admin'):
            self.role_filter = Role.name.in_(['operator'])
        else:
            self.role_filter = Role.name.in_(['superadmin', 'admin', 'operator'])

        return fn(self, *args, **kwargs)

    def scaffold_form(self):
        form = super(ViewForCreatingAdminUsers, self).scaffold_form()
        form.roles = QuerySelectMultipleField(
            query_factory=lambda: self.session.query(Role).filter(self.role_filter),
            widget=Select2Widget(multiple=False)  # change this to True if you allow multiple roles
        )
        return form

_run_view func总是在request上下文中调用,所以每当我们点击创建一个表单时,就会调用该func并且我们可以使用role_filter。

附:根据上面的代码用例是admin应该只能创建operator

© www.soinside.com 2019 - 2024. All rights reserved.