2013-05-18 6 views
7

Io ho un paio di istruzioni DDL personalizzati che voglio correre dietro creare la tabella:Come si ottiene l'alambicco per emettere DDL personalizzato su after_create?

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(); 
""") 

e li ho attaccati in questo modo:

event.listen(Session.__table__, 'after_create', update_function) 
event.listen(Session.__table__, 'after_create', update_trigger) 

Quando faccio create_all, ho ottenere lo SQL mi aspetto:

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(); 

Ma quando aggiorno utilizza Alembic, non sembrano le dichiarazioni:

-- 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'); 

C'è un modo per fare in modo che l'alambicco attivi gli eventi 'after_create'?

risposta

8

Gli eventi di livello tabella before_create/after_create vengono emessi (solo non quelli di livello metadati). devi assicurarti che qualsiasi cosa accada nel tuo script env.py alla fine coinvolga quegli ascoltatori di eventi in fase di configurazione.

Il codice che avete qui sembra un po 'sospetto:

event.listen(Session.__table__, 'after_create', update_function) 
event.listen(Session.__table__, 'after_create', update_trigger) 

Session.__table__ qui sarebbe solo un singolo Table istanza e che probabilmente non è quello che ci si vede nello script alambicco. Il comando alambicco create_table crea un Table a livello locale e solo gestisce un creare su di esso, in modo avresti bisogno di ascoltare tutti oggetti tabella a livello globale:

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

se questi eventi sono solo per questo una tabella specifica, però, allora si non userebbe alcun evento, metterà semplicemente il DDL() per quei trigger direttamente nello script di migrazione, subito dopo dove chiama lo create_table().

+0

Grazie per la spiegazione. –

4

Ampliando la risposta di @ zzzeek, ​​questo helper funziona per me:

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)) 

Allora faresti:

on_table_create(Session, update_function) 
on_table_create(Session, update_trigger) 
Problemi correlati