Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 如何让alembic在创建后发出自定义DDL?_Postgresql_Sqlalchemy_Ddl_Alembic - Fatal编程技术网

Postgresql 如何让alembic在创建后发出自定义DDL?

Postgresql 如何让alembic在创建后发出自定义DDL?,postgresql,sqlalchemy,ddl,alembic,Postgresql,Sqlalchemy,Ddl,Alembic,我有两个自定义DDL语句,我想在创建表之后运行它们: update_function = DDL(""" CREATE OR REPLACE FUNCTION update_timestamp()

我有两个自定义DDL语句,我想在创建表之后运行它们:

update_function = DDL("""                                                                                                                                                       
CREATE OR REPLACE FUNCTION update_timestamp()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = now();
    RETURN NEW;
END;
$$ language 'pgplsql';
""")

update_trigger = DDL("""
CREATE TRIGGER update %(table)s_timestamp BEFORE UPDATE
ON %(table)s FOR EACH ROW EXECUTE PROCEDURE update_timestamp();
""")
我把它们贴在下面:

event.listen(Session.__table__, 'after_create', update_function)
event.listen(Session.__table__, 'after_create', update_trigger)
当我执行
create\u all
时,我得到了我期望的SQL:

CREATE OR REPLACE FUNCTION update_timestamp()
RETURNS TRIGGER AS $$ 
BEGIN
    NEW.updated_at = now();
    RETURN NEW;
END;
$$ language 'pgplsql';


CREATE TRIGGER update session_timestamp BEFORE UPDATE
ON session FOR EACH ROW EXECUTE PROCEDURE update_timestamp();
但当我使用Alembic升级时,不会出现以下语句:

-- Running upgrade c0d470e5c81 -> 6692fad7378

CREATE TABLE session (
    created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT 'CURRENT_TIMESTAMP', 
    updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT 'CURRENT_TIMESTAMP', 
    id VARCHAR(32) NOT NULL, 
    owner_id INTEGER, 
    database_id VARCHAR(32), 
    content TEXT, 
    PRIMARY KEY (id), 
    FOREIGN KEY(database_id) REFERENCES database (id), 
    FOREIGN KEY(owner_id) REFERENCES users (id)
);

INSERT INTO alembic_version (version_num) VALUES ('6692fad7378');

有没有办法让alembic触发“创建后”事件?

发出创建前/创建后事件的表级别(而不是元数据级别的事件)。您需要确保在env.py脚本中发生的任何事情最终都涉及到正在设置的事件侦听器

这里的代码看起来有点可疑:

event.listen(Session.__table__, 'after_create', update_function)
event.listen(Session.__table__, 'after_create', update_trigger)
Session.\uuuu table\uuuuu
这里只有一个
table
实例,这可能不是您在alembic脚本中看到的。alembic
create\u table
命令在本地创建一个
table
,并在其上运行一个create,因此您需要全局侦听所有表对象:

from sqlalchemy import Table
event.listen(Table, 'after_create', update_function)
event.listen(Table, 'after_create', update_trigger)

如果这些事件只针对这一个特定的表,那么您就不会使用任何事件,您只需将这些触发器的DDL()直接放在迁移脚本中,就在它调用
create_table()

展开@zzzeek的答案之后,这个助手对我有用:

from sqlalchemy import Table
from sqlalchemy.event import listen
from functools import partial

def on_table_create(class_, ddl):

    def listener(tablename, ddl, table, bind, **kw):
        if table.name == tablename:
            ddl(table, bind, **kw)

    listen(Table,
           'after_create',
           partial(listener, class_.__table__.name, ddl))
然后你会做:

on_table_create(Session, update_function)
on_table_create(Session, update_trigger)

这个解决方案对我帮助很大:

因此,如果您有一个带有侦听器的DDL,请将其放入一个变量中:

create_table_ddl = DDL("...").execute_if(dialect='postgresql')
drop_table_ddl = DDL("...").execute_if(dialect='postgresql')


event.listen(Model.__table__, 'after_create', create_table_ddl)
event.listen(Model.__table__, 'before_drop', drop_table_ddl)

在迁移过程中手动执行此操作:

def upgrade():
    create_table_ddl(target=None, bind=op.get_bind())

def upgrade():
    drop_table_ddl(target=None, bind=op.get_bind())

Alembic不会调用您的表事件

谢谢您的解释。愚蠢的问题:如果我们希望在每个表中运行“event.listen”,我们在Alembic to的何处添加“event.listen”?它在env.py中吗?