Flask-Admin针对不同角色的不同表单和column_list

时间:2017-11-23 11:21:01

标签: python flask flask-admin

关注此问题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的任何类。

1 个答案:

答案 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