Alembic / Flask-Migrate未检测到after_create事件

问题描述 投票:3回答:1

我有一个简单的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创建和管理我的触发器(即,在after_create事件上运行的自定义DDL)?

flask sqlalchemy flask-sqlalchemy alembic flask-migrate
1个回答
0
投票

我遇到了同样的问题尝试使用可替换对象的解决方案,但没有工作:

我设法通过编辑迁移脚本并执行触发器创建查询来使其工作。

以下是步骤:

  • 运行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:更优雅的解决方案应该是什么建议here

使用可替换对象,尝试过但它不起作用可能是我的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)

希望它能帮助别人......

© www.soinside.com 2019 - 2024. All rights reserved.