Alembic/Flask-Migrate не обнаруживает события after_create
У меня есть простая модель Flask-SQLAlchemy (с прослушивателем событий для создания триггера):
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Confirm(db.Model):
created = db.Column(db.DateTime, default=db.func.current_timestamp(), nullable=False)
modified = db.Column(db.DateTime, default=db.func.current_timestamp(), onupdate=db.func.current_timestamp(), nullable=False)
id = db.Column(db.String(36), primary_key=True)
class ConfirmOld(db.Model):
orig_created = db.Column(db.DateTime)
orig_modified = db.Column(db.DateTime)
orig_id = db.Column(db.String(36))
confirm_delete = DDL('''\
CREATE TRIGGER confirm_delete
BEFORE DELETE
ON confirm FOR EACH ROW
BEGIN
INSERT INTO confirm_old ( orig_created, orig_modified, orig_id )
VALUES ( OLD.created, OLD.modified, OLD.id );
END;
''')
event.listen(Confirm.__table__, 'after_create', confirm_delete)
Когда я запускаю миграцию и обновление Alembic, TRIGGER не создается (в MySQL). Тем не менее, он создается и работает правильно, когда я использую db.create_all().
Можно ли заставить Alembic / Flask-Migrate создавать и управлять моими триггерами (т. Е. Пользовательским DDL, который запускается для событий after_create)?
2 ответа
Я столкнулся с той же проблемой, пытался решить с помощью Replacable объекта, но не работал:
Мне удалось заставить его работать, отредактировав скрипт миграции и выполнив запрос на создание триггера.
Вот шаг:
Бежать
flask db migrate -m 'adding custom trigger on table x
он создаст сценарий миграции для вас в подпапке версии папки миграции.проверьте папку, созданную в версии, и отредактируйте ее следующим образом:
создайте свой триггерный запрос следующим образом:
в файле:
trigger = '''
CREATE TRIGGER confirm_delete
BEFORE DELETE
ON confirm FOR EACH ROW
BEGIN
INSERT INTO confirm_old ( orig_created, orig_modified, orig_id )
VALUES ( OLD.created, OLD.modified, OLD.id );
END;
'''
в методе обновления:
добавьте эту строку:
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
# ### end Alembic commands ###
### add your queries here execute
op.execute(trigger)
Если вы бежите flask db upgrade
он выполнит запрос и обновит базу данных
Чтобы понизить версию базы данных, добавьте это в метод понижения:
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
# ### end Alembic commands ###
op.execute('drop trigger if exists confirm_delete on confirm cascade;')
Если вы проверите вашу базу данных изменения будут применены.
PS: более элегантное решение должно быть то, что предлагается здесь
со Сменным объектом, попробовал это, но Это не работает, возможно, мой alembic не обновляет.
Вот как должно выглядеть решение:
создайте класс ReplaceableObjects:
class ReplaceableObject(object):
def __init__(self, name, sqltext):
self.name = name
self.sqltext = sqltext
создайте его с помощью оператора запроса.
delete_trigger = ReplaceableObject('delete_trigger', trigger)
Обновите функцию обновления и понижения, как это:
def upgrade():
op.create_sp(delete_trigger)
def downgrade():
op.drop_sp(delete_trigger)
Надеюсь, что это поможет другим...
во Flask прослушивание игнорируется.
Исправлено это с помощью таблицы вместо этого.
def after_create_table_handler(table: Table, conn: Connection, **kwargs):
pass
event.listen(Table, 'after_create', after_create_table_handler)