Решил это.
Потратил некоторое время на изучение ModelView
исходного кода , и, действительно, ничего подобного не было реализовано.Ну что ж, пришлось закатать рукава.
Мы должны обернуть все запросы к базе данных с помощью switch_db
менеджера контекста.Документация Flask-Admin содержит список методов, необходимых для реализации бэкэнда модели .Таким образом, если какой-либо запрос к базе данных имеет место, он есть.
Изучив реализацию этих методов в ModelView
, мы можем выяснить, что запросы Mongoengine могут выполняться только в методах get_list
, get_one
, create_model
, update_model
и delete_model
,
Теперь мы унаследовали от ModelView
и обернули эти методы необходимым диспетчером контекста:
class SwitchableModelView(ModelView):
database_alias = DEFAULT_CONNECTION_NAME
# Override query methods to add database switchers
def get_list(self, *args, **kwargs):
with switch_db(self.model, self.database_alias):
# It's crucial that the query gets executed immediately,
# while in the switch_db context,
# so we need to override the `execute` argument.
kwargs['execute'] = True
return super().get_list(*args, **kwargs)
def get_one(self, *args, **kwargs):
with switch_db(self.model, self.database_alias):
return super().get_one(*args, **kwargs)
def create_model(self, *args, **kwargs):
with switch_db(self.model, self.database_alias):
return super().create_model(*args, **kwargs)
def update_model(self, *args, **kwargs):
with switch_db(self.model, self.database_alias):
return super().update_model(*args, **kwargs)
def delete_model(self, *args, **kwargs):
with switch_db(self.model, self.database_alias):
return super().delete_model(*args, **kwargs)
Затем мы можем переключить базу данных в наших представлениях следующим образом:
class EntityView(SwitchableModelView):
can_delete = True
can_edit = True
can_view_details = True
can_create = True
can_export = True
# Now it works!
database_alias = SECOND_DB_ALIAS
def __init__(self):
super().__init__(Entity, name="Entities")
Если database_alias
опущено, соединение по умолчанию все равно будет использоваться, что приведет к поведению ванили ModelView
.
Я проверил это.Работает.
Хотя у меня есть некоторые опасения по поводу эффективности и надежности этого кода.Как я уже говорил, switch_db
на данный момент не является потокобезопасным.База данных включается на весь класс Entity
при входе и выходе из контекста.Итак, я не уверен, как он будет себя вести при высокой нагрузке в многопоточном приложении Flask и будут ли проблемы с состоянием гонки.
Если кто-нибудь придумает лучший подход к проблеме или с какой-либоулучшения этого кода, я был бы рад услышать.