Flask-Admin different forms and column_list for different roles

前端 未结 1 1870
旧时难觅i
旧时难觅i 2021-01-13 21:18

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

相关标签:
1条回答
  • 2021-01-13 21:59

    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
    
    0 讨论(0)
提交回复
热议问题