Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » Web
  • » Flask-SQLAlchemy: Как независимо использовать одну модель в Blueprints? [RSS Feed]

#1 Апрель 30, 2016 20:44:49

Marta
Зарегистрирован: 2016-01-20
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

Flask-SQLAlchemy: Как независимо использовать одну модель в Blueprints?

Здравствуйте.

Пишу большое приложение на Flask, используя SQLAlchemy для работы с базой. Причем приложение обслуживает несколько доменов. В связи с этим, весь функционал разделен на пакеты, которые потом регистрируются (мол “пакет - домен - префикс”).

С разделением и роутингом проблем нет, просто включила host_matching и создала новый класс на основе Blueprint. Затем просто переопределила конструктор и метод-декоратор route, чтобы каждый раз не указывать аргумент host (он будет передан конструктору и храниться как свойство класса при регистрации blueprint'ов).

Вся проблема в том, что Blueprint'ы могут регистрироваться несколько раз, причем эта регистрация по факту просто добавляет в таблицу роутинга новые маршруты. Однако импортирование в Python - это не тупой include и модули загружаются один раз и потом используются везде, где были заимпортированы. То есть, запросы у дважды зарегистрированного Blueprint'а будет обрабатывать однажды загрузившийся пакет.

Меня пока не озадачивает, что вьюхи будут одними и теми же функциями, но что делать с моделями? Они должны быть независимы для двух зарегистрированных Blueprint'ов. Мне надо как-то динамически создать для каждого Blueprint'а новую модель, наследуя эталонную? Но тогда еще надо что-то делать и со связями с другими моделями (которые могут быть так же копиями). Есть модуль copy, но это тоже магия.

Я предполагаю, что в SQLAlchemy есть какой-то механизм для решения этих проблем, но гуглинг на тему клонирования моделей особо ничего не дал. Так же может моя идея построения приложения не так хороша (по идее можно для каждого домена использовать свой экземпляр application, но пока проект не на столько большой - как-то проще не заморачиваться с их взаимодействием и использовать один).

Офлайн

#2 Апрель 30, 2016 22:13:18

ayb
Зарегистрирован: 2014-04-01
Сообщения: 297
Репутация: +  24  -
Профиль   Отправить e-mail  

Flask-SQLAlchemy: Как независимо использовать одну модель в Blueprints?

О боже, какое клонирование моделей

Офлайн

#3 Май 1, 2016 00:03:18

Marta
Зарегистрирован: 2016-01-20
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

Flask-SQLAlchemy: Как независимо использовать одну модель в Blueprints?

ayb
О боже, какое клонирование моделей
Если не это, то что?

Мне кажется, что это как-то вяжется с Declarative в SQLAlchemy. Однако я не вычитала еще всю документацию по этому тулкиту и не совсем понимаю то оно или нет…

Отредактировано Marta (Май 1, 2016 03:03:10)

Офлайн

#4 Май 1, 2016 09:47:04

4kpt_IV
Зарегистрирован: 2016-01-08
Сообщения: 999
Репутация: +  49  -
Профиль   Отправить e-mail  

Flask-SQLAlchemy: Как независимо использовать одну модель в Blueprints?

Модели будут одинаковыми? Или все же будут изменятся?

Офлайн

#5 Май 1, 2016 09:54:19

4kpt_IV
Зарегистрирован: 2016-01-08
Сообщения: 999
Репутация: +  49  -
Профиль   Отправить e-mail  

Flask-SQLAlchemy: Как независимо использовать одну модель в Blueprints?

Marta
В связи с этим, весь функционал разделен на пакеты, которые потом регистрируются (мол “пакет - домен - префикс”).

Подробнее. Что значит “Регистрируются”.

Marta
С разделением и роутингом проблем нет, просто включила host_matching и создала новый класс на основе Blueprint. Затем просто переопределила конструктор и метод-декоратор route, чтобы каждый раз не указывать аргумент host (он будет передан конструктору и храниться как свойство класса при регистрации blueprint'ов).

Тоже подробнее. Напоминает какой-то адовый овер…

P.S. В питоне нет конструктора

Отредактировано 4kpt_IV (Май 1, 2016 10:04:02)

Офлайн

#6 Май 2, 2016 02:23:15

Marta
Зарегистрирован: 2016-01-20
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

Flask-SQLAlchemy: Как независимо использовать одну модель в Blueprints?

4kpt_IV
Модели будут одинаковыми? Или все же будут изменятся?
Да. По факту надо более красивое решение, чем просто скопировать пакет под другим именем (сейчас считаю это наименее магическим путем, но не красивым). Хотя тоже: что вы конкретно понимаете под одинаковостью?

4kpt_IV
Подробнее. Что значит “Регистрируются”.
Метод Flask.register_blueprint().

4kpt_IV
Тоже подробнее. Напоминает какой-то адовый овер…
Как-то так (этот код не запускала, но примерно такое накидывала и работало):
class Mod(Blueprint):
    def __init__(self, name, import_name, static_folder=None,  # чем __init__() не конструктор?
                 static_url_path=None, template_folder=None,
                 url_prefix=None, subdomain=None, url_defaults=None,
                 host=None):
        super().__init__(name, import_name, static_folder, static_url_path, template_folder,  # py3
                         url_prefix, subdomain, url_defaults)
        self.host = host
    def route(self, rule, **options):
        def decorator(f):
            if 'host' not in options:
                options['host'] = self.host
            endpoint = options.pop("endpoint", f.__name__)
            self.add_url_rule(rule, endpoint, f, **options)
            return f
        return decorator
foo = Mod('foo', __name__,  host='example.org')
@foo.route('/')
def hi():
    return 'Hi from example!'
app = Flask(__name__)
app.url_map.host_matching = True
app.register_blueprint(foo)

Офлайн

#7 Май 2, 2016 08:06:20

ayb
Зарегистрирован: 2014-04-01
Сообщения: 297
Репутация: +  24  -
Профиль   Отправить e-mail  

Flask-SQLAlchemy: Как независимо использовать одну модель в Blueprints?

Внимание вопрос : зачем копировать модели ?

Офлайн

#8 Май 2, 2016 10:42:15

4kpt_IV
Зарегистрирован: 2016-01-08
Сообщения: 999
Репутация: +  49  -
Профиль   Отправить e-mail  

Flask-SQLAlchemy: Как независимо использовать одну модель в Blueprints?

Marta

Вопрос первый (Ваш). Тем, что есть еще __new__…

Вопрос второй (ayb). Да не за чем. Можно просто создавать разные БД по одним и тем же моделям по названиям blueprint, но только в том случае, если не нужно делать часто выборки по общим данным. Если же нужно, то легче создать базовую таблицу со спецификатором и по нему фильтровать, хотя я все равно склоняюсь к нескольким БД (зависит от сложность кроссбазовых запросов).

Ну и на по-следок. Таки да. Адовый хардкор. Слишком много магии. Можно значительно проще. Гляньте в сторону Flask-Classy. Там можно собирать приложение из схожих кусков, а blueprint использовать как лоток для сборки. Плюс это все дело можно наследовать и подключать под разными настройками.

Офлайн

#9 Май 5, 2016 02:45:22

Marta
Зарегистрирован: 2016-01-20
Сообщения: 10
Репутация: +  0  -
Профиль   Отправить e-mail  

Flask-SQLAlchemy: Как независимо использовать одну модель в Blueprints?

4kpt_IV, спасибо за ответ.

4kpt_IV
Тем, что есть еще __new__…
Возможно, вы правы и упоминать понятие конструктора в рамках Python может быть не корректно. Однако __new__() же возвращает объект класса, а __init__() его инициализирует (настраивает) - вполне себе тот же __construct из того же PHP (да и в других языках нечто подобное). Методов есть много, вплоть до перегрузки операторов при их применение к данному классу.

4kpt_IV
Можно просто создавать разные БД по одним и тем же моделям по названиям blueprint, но только в том случае, если не нужно делать часто выборки по общим данным.
Иметь 20 баз под каждый Blueprint - не вариант. Можно разделять по доменам (есть же Bind в SQLAlchemy), однако это не решает вопрос двух Blueprint'ов на одном домене.

4kpt_IV
Если же нужно, то легче создать базовую таблицу со спецификатором и по нему фильтровать, хотя я все равно склоняюсь к нескольким БД (зависит от сложность кроссбазовых запросов).
Тоже думала завести дополнительные колонки в БД. Но это лишает прозрачности того, что Blueprint не думает сколько раз его подключают и как. Если бы работала с базой напрямую, составляя SQL запросы, то просто бы сделала префиксы для таблиц. Возможно, есть подобный вариант в ORM? Теоретически можно играть с маппингом…

4kpt_IV
Можно значительно проще. Гляньте в сторону Flask-Classy.
Да, смотрела это расширение. Его я буду использовать, но пока разбираюсь без него с ключевыми вопросами. Оно дает гибкость, но в нем так же придется переопределить методы для введения параметра host (host matching в werkzeug - это то, что нужно, в отличии от subdomain) или форкать (что плохо. если так, то можно попробовать pull request послать). Но опять же никаких вопросов оно не снимает.

Пока читаю документацию SQLAlchemy, чтобы полностью разобраться в ней и найти приемлимый способ.

Офлайн

#10 Май 5, 2016 07:44:25

4kpt_IV
Зарегистрирован: 2016-01-08
Сообщения: 999
Репутация: +  49  -
Профиль   Отправить e-mail  

Flask-SQLAlchemy: Как независимо использовать одну модель в Blueprints?

Marta
Иметь 20 баз под каждый Blueprint - не вариант. Можно разделять по доменам (есть же Bind в SQLAlchemy), однако это не решает вопрос двух Blueprint'ов на одном домене.

Блупринт не логическая единица. Не надо так думать. Считайте это просто способом упаковки роутов к вьюхам. Нет никакой логической связи между блупринтом и базами… Ну и зачем два блупринта на один домен я так и не понял

Marta
Да, смотрела это расширение. Его я буду использовать, но пока разбираюсь без него с ключевыми вопросами. Оно дает гибкость, но в нем так же придется переопределить методы для введения параметра host (host matching в werkzeug - это то, что нужно, в отличии от subdomain) или форкать (что плохо. если так, то можно попробовать pull request послать). Но опять же никаких вопросов оно не снимает.

Зачем? Судя по Вашему предыдущему коду Вы же захардкориваете host matching в блупринте…

Marta
Иметь 20 баз под каждый Blueprint - не вариант. Можно разделять по доменам (есть же Bind в SQLAlchemy), однако это не решает вопрос двух Blueprint'ов на одном домене.

Marta
Тоже думала завести дополнительные колонки в БД. Но это лишает прозрачности того, что Blueprint не думает сколько раз его подключают и как.

У меня возникает ощущение, что Вы пытаетесь решить три проблемы одним шагом. Это совершенно неверно. Такого решения нет. Так что помочь мне просто не чем Хотя мог бы посоветовать тогда собирать свои модели под конкретный блупринт (через подмену Basе) и подсовывать их ему через DI, но у Вас и так в голове сейчас каша, поэтому откланиваюсь

Отредактировано 4kpt_IV (Май 5, 2016 08:12:38)

Офлайн

  • Начало
  • » Web
  • » Flask-SQLAlchemy: Как независимо использовать одну модель в Blueprints?[RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version