关注此问题Flask-Admin Role Based Access - Modify access based on role我不了解如何实现基于角色的视图,尤其是关于表单和列_列表。
如果用户是普通用户或超级用户,我希望MyModelView
显示不同的列。
覆盖is_accessible
中的MyModelView
完全无效
from flask_security import Security, SQLAlchemyUserDatastore, current_user
class MyModelView(SafeModelView):
# ...
def is_accessible(self):
if current_user.has_role('superuser'):
self.column_list = superuser_colum_list
self.form_columns = superuser_form_columns
else:
self.column_list = user_colum_list
self.form_columns = user_form_columns
return super(MyModelView, self).is_accessible()
# Has same effect as
def is_accessible(self):
return super(MyModelView, self).is_accessible()
并定义条件类属性不起作用,因为current_user
未定义(NoneType
错误,因为AttributeError on current_user.is_authenticated())。在ModelView的__init__
中做同样的事情,current_user
仍未定义
class MyModelView(SafeModelView):
#[stuff]
if current_user.has_role('superuser'):
column_list = superuser_colum_list
form_columns = superuser_form_columns
else:
column_list = user_colum_list
form_columns = user_form_columns
#[other stuff]
仅供参考,SafeModelView
可以是在前面提到的问题中继承自dgBaseView
的任何类。
答案 0 :(得分:3)
我通常将视图类属性(例如column_list
)定义为属性。它允许您为它们添加一些动态逻辑:
from flask import has_app_context
from flask_security import current_user
class MyModelView(SafeModelView):
@property
def column_list(self):
if has_app_context() and current_user.has_role('superuser'):
return superuser_column_list
return user_column_list
@property
def _list_columns(self):
return self.get_list_columns()
@_list_columns.setter
def _list_columns(self, value):
pass
使用此方法的问题(以及为什么在column_list
函数中重新分配is_accessible
值不起作用的原因)是许多视图属性在应用程序启动时缓存并存储在私有属性中。例如column_list
缓存在_list_columns
属性中,因此您还需要重新定义它。您可以在flask_admin.model.base.BaseModelView._refresh_cache方法中查看此缓存的工作原理。
此处需要Flask has_app_context
方法,因为当您的column_list
变量尚无有意义的值时,在应用程序启动时会发生首次current_user
读取。
使用form_columns
属性也可以这样做。属性将如下所示:
@property
def form_columns(self):
if has_app_context() and current_user.has_role('superuser'):
return superuser_form_columns
return user_form_columns
@property
def _create_form_class(self):
return self.get_create_form()
@_create_form_class.setter
def _create_form_class(self, value)
pass
@property
def _edit_form_class(self):
return self.get_edit_form()
@_edit_form_class.setter
def _edit_form_class(self, value):
pass