Flask-Admin: формировать леса по запросу

Сценарий

Я создаю интерфейс CRUD с помощью Flask-Admin. Я использую 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)

учреждение.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(), который вызывается при каждом запросе. Однако мне нужно было бы воспроизвести логику формирования формы flask-admin в render(), что далеко не тривиально (или чисто).


person skedastik    schedule 20.08.2015    source источник


Ответы (1)


Решение состоит в том, чтобы переопределить два метода:

  • 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()
person skedastik    schedule 21.08.2015