Как можно построить архитектуру действительно большого Flask приложения?

Разрабатываю большое Flask приложение, возникла проблема в его архитектуре. В целом то мне понравился подход в https://github.com/sean-/flask-skeleton, что можно использовать Blueprint (так то подобных примеров и гайдов полно).

Однако приложение большое тем, что оно не просто разбито на несколько файлов для удобства, а обслуживает несколько сайтов (хостов/поддоменов - будет задаваться в конфиге), которые имеют пересечение функционала (следовательно, есть общий код для этого) и между ними поддерживается общая сессия пользователя и сама база с ними (и некоторыми другими данными).

В целом то архитектура построена сейчас таким образом, что есть некоторое ядро, где созданы общие модели, классы для всех сайтов, а так же создается приложение Flask, подключено расширение Flask-SQLAlchemy. Так же было включена поддержка host matching и реализовано указание хоста в Blueprint. Сами же блоки функционала хранятся в индивидуальных пакетах, где создается Blueprint'ы под это дело, определены формы, модели (они импортируют из ядра созданный объект класса SQLAlchemy из расширения), вьюхи. В целом, задумка такая же, как и в указанном скелетоне.

Казалось бы все хорошо, регистрируй Блюпринты в приложении Flask и радуйся. Но проблема в том, что Blueprint по факту просто регистрирует в таблице роутинга одни и те же импортированными вьюхи под разными маршрутами (предполагается регистрация одного Блюпринта множество раз - Flask это позволяет). И даже не в этом корень проблемы: модель то в блоке функционала остается той же самой и работает с теми же самыми данными. По факту по разным адресам будет одно и то же, что сводит весь смысл в приложении на нет.

Сначала пытался решить проблему с моделями, но начал задумываться: а правильно ли была построена архитектура приложения? Не слишком ли требовать от Blueprint'а и пакетов питона полной изоляции? Возможно, надо двигаться в сторону создания конкретных экземпляров моделей из абстрактной и подсовывать это в вьюху через паттерн DI? Возможно, вовсе стоит уже сейчас прибегнуть к паттерну фабрики приложения и создавать Flask приложение для каждого сайта (но тогда надо прокидывать сессию и прочие общности между ними)?

Если кратко и на пальцах, то хотелось бы построить архитектуру, где пускай есть site1.ru, site2.ru, site3.ru. Базы пользователей и регистрация у них общая, сессия тоже. Имеется общий код в виде блоков, который пускай реализуют функционал тех же новостей, статей и форумов. И в конфиге бы указывалось, что на site1.ru нужны новости на главном (префикс /), на site2.ru нужно два каталога статей (префиксы /articles_1/ и /articles_2/), на site3.ru нужны новости (префикс /news/) и форум (префикс /forum/). И, понятное дело, что эти, так сказать, блоки кода должны оперировать с разным контентом.

Ну и отвечу на некоторые возможные вопросы:
  • Flask выбран потому, что он минималистичен и позволяет гибко строить приложения (да, расплата за это то, что необходимо местами делать связки и строить архитектуру самостоятельно. но гибкость, минималистичность, мощность я ценю
  • Django не выбрал потому, что она удобна скорее для типовых решений. мне не все нравится как в ней устроено, пришлось бы так же переписывать и реализовывать некоторые вещи
  • Да, мои знания в Python не идеальны, но мне нравится погружаться в нечто новое с помощью реальных проектов, а не вызубривать тонны книжек перед этим или строя очередной учебный мироклон твиттера, где описанные проблемы просто не поднимаются
  • Внутренности работы SQLAlchemy мне до конца не ясны пока, но мне начинает казаться, что надо воевать не с ней, а в архитектуре просто допущен косяк, почему все и выходит так...


P.S. Извиняюсь за столь длинную портянку, но хотелось бы решить проблему красиво, так как бьюсь над ней уже некоторое время. А решать колхозом вроде складывания всего контента всего в одну модель (точнее таблицу, так как на нее модель мапится) - не хотелось бы. Если бы не было ORM, то в чистом SQL решилось бы простыми префиксами у таблиц. Но ORM, Python - это для меня пока новый стек технологий, которые очень бы хотелось уже использовать, а не сидеть в php4-style.
  • Вопрос задан
  • 2768 просмотров
Пригласить эксперта
Ответы на вопрос 3
просто переходите на Django. меньше головной боли получите
Ответ написан
sim3x
@sim3x
Если ты хочешь построить большое приложение, то у тебя уже сразу есть большая проблема
Разделяй
Тебе не обязательно иметь, все в одной бд и на одном сайте
Сделай аккаунты на одном домене - одно приложение
А все остальное делай через развертывание на новом домене

А про фласк, я не видел саксесс сториес
Ответ написан
@asd111
Динамический выбор таблицы для одной и той же модели в django обычно решается примерно так:
def get_model(db_table):
  class MyClassMetaclass(models.base.ModelBase):
    def __new__(cls, name, bases, attrs):
      name += db_table
      return models.base.ModelBase.__new__(cls, name, bases, attrs)

  class MyClass(models.Model):
    __metaclass__ = MyClassMetaclass

    class Meta:
      db_table = db_table

  return MyClass

my_model = get_model('29345794_table')
my_model.objects.filter( ...


Суть в том чтобы при создании модели динамически указать название таблицы. А всё остальное будет работать как обычно. Думаю как это сделать под sqlAlchemy разберетесь самостоятельно.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы