Following up on this question Flask-Admin Role Based Access - Modify access based on role I don\'t understand how to implement role-based views, especially regarding the for
I usually define view class attributes such as column_list
as properties. It allows you to add some dynamic logic to them:
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
The problem with using this approach (and why your reassigning of column_list
values in is_accessible
function took no effect) is that many view attributes are cached on application launch and stored in private attributes. column_list
for example is cached in _list_columns
attribute so you need to redefine it as well. You can look how this caching works in flask_admin.model.base.BaseModelView._refresh_cache method.
Flask has_app_context
method is needed here because first column_list
read is happened on application launch when your current_user
variable has no meaningful value yet.
The same can be done with form_columns
attribute. The properties will look like this:
@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