Flask-Admin:每个请求的表格脚手架

时间:2015-08-20 18:20:24

标签: python flask flask-admin

场景

我正在使用Flask-Admin创建CRUD界面。我使用flask.session来确定当前登录用户的角色。基于此角色,我希望根据请求以不同方式构建表单/视图。

代码

index.py

from institution import InstitutionView

app = flask.Flask(...)

admin = flask_admin.Admin(...)

# artificial user data
user_dict = {
    ...
    'role' : 'Teacher'
}

# pass user data to institution view
institutionView = InstitutionView(..., user=user_dict)
admin.add_view(institutionView)

institution.py

class InstitutionView(ModelView):
    ...

    def scaffold_list_columns(self):
        # generate columns dynamically
        if self._user['admin_role'] == 'Teacher':
            return ('name', 'c_date', 'e_date')
        return ('name', 'foo', 'bar', 'c_date', 'e_date')

    def scaffold_form(self):
        # generate fields dynamically
        if self._user['admin_role'] == 'Teacher':
            ...

问题

到目前为止,我已经人工将用户数据注入InstitutionView构造函数。现在这是一个问题,我想从flask.session中提取数据。 脚手架需要在请求上下文中进行,但它目前在应用程序初始化时发生。

我是Flask的新手,所以我很可能认为这一切都错了。

更新2015.8.20

一种可能性是覆盖在每个请求时调用的flask_admin.base.BaseView.render()。但是,我需要在render()内重现flask-admin的形式脚手架逻辑,这远非琐碎(或干净)。

1 个答案:

答案 0 :(得分:4)

解决方案是覆盖两种方法:

  • flask_admin.model.base.BaseView._handle_view()
  • flask_admin.model.base.BaseModelView._refresh_cache()

代码:

class InstitutionView(ModelView):
    ...

    # _handle_view called every request
    def _handle_view(self, name, **kwargs):
        if not flask_login.current_user.is_authenticated():
            return self.inaccessible_callback(name, **kwargs)

        # re-scaffold views every request
        self._refresh_cache()

        return super(InstitutionView, self)._handle_view(name, **kwargs)

    # _refresh_cache called once when view is added to admin interface
    def _refresh_cache(self):
        # do not _refresh_cache outside of a request context
        if not flask_login.current_user:
            # init members with empty tuples to avoid instantiation error
            self._list_columns = ()
            return
        super(InstitutionView, self)._refresh_cache()