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)
Другие вопросы по тегам