Flask-Admin 不同的形式和 column_list 不同的角色

Flask-Admin different forms and column_list for different roles

跟进这个问题我不明白如何实现基于角色的视图,尤其是关于表单和column_lists。

假设我希望 MyModelView 在用户是普通用户或超级用户时显示不同的列。

MyModelView 中覆盖 is_accessible 根本没有效果

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()

和定义条件 class 属性也不起作用,因为 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 继承的任何 class。

我通常定义视图class属性如column_list作为properties。它允许您向它们添加一些动态逻辑:

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

使用这种方法的问题(以及为什么您在 is_accessible 函数中重新分配 column_list 值没有效果)是许多视图属性在应用程序启动时缓存并存储在私有属性中。例如 column_list 缓存在 _list_columns 属性中,因此您也需要重新定义它。您可以在 flask_admin.model.base.BaseModelView._refresh_cache 方法中查看此缓存的工作原理。

此处需要 Flask has_app_context 方法,因为当您的 current_user 变量还没有有意义的值时,第一个 column_list 读取发生在应用程序启动时。

同样可以用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