用于添加具有特定角色的用户的 Flask-Admin 权限
Flask-Admin permissions for adding user with specific role
我使用 Flask-Admin 和 Flask-Security 为我的 Python 应用程序实现管理面板。以下是 User
和 Role
的模型:
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.
为此,您必须自定义一些内容。
我建议如下:
在您的用户模型中添加此方法以检查用户是否具有特定角色:
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()
方法
虽然 的回答提供了关于需要做什么的简明想法,但根据我的观察,我认为它是不完整的。这是因为
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 可用。
P.S。根据上述代码的用例是 admin
应该只能创建 operator
.
我使用 Flask-Admin 和 Flask-Security 为我的 Python 应用程序实现管理面板。以下是 User
和 Role
的模型:
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.
为此,您必须自定义一些内容。
我建议如下:
在您的用户模型中添加此方法以检查用户是否具有特定角色:
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()
方法
虽然 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 可用。
P.S。根据上述代码的用例是 admin
应该只能创建 operator
.