2012-01-18 24 views
9

Tengo campos created_by y updated_by en cada modelo. Estos campos se llenan automáticamente con sqlalchemy.event.listen (anteriormente MapperExtension). Para cada modelo, escribo: SQLAlchemy "event.listen" para todos los modelos

event.listen(Equipment, 'before_insert', get_created_by_id) 
event.listen(Equipment, 'before_update', get_updated_by_id) 

Cuando el modelo fue una gran cantidad de código se pone fea. ¿Es posible aplicar event.listen inmediatamente a todos los modelos o a varios?

UPD: Estoy tratando de hacerlo:

import pylons 
from sqlalchemy import event, sql 
from sqlalchemy import Table, ForeignKey, Column 
from sqlalchemy.databases import postgresql 
from sqlalchemy.schema import UniqueConstraint, CheckConstraint 
from sqlalchemy.types import String, Unicode, UnicodeText, Integer, DateTime,\ 
          Boolean, Float 
from sqlalchemy.orm import relation, backref, synonym, relationship 
from sqlalchemy import func 
from sqlalchemy import desc 
from sqlalchemy.orm.exc import NoResultFound 

from myapp.model.meta import Session as s 
from myapp.model.meta import metadata, DeclarativeBase 

from pylons import request 

def created_by(mapper, connection, target): 
    identity = request.environ.get('repoze.who.identity') 
    if identity: 
     id = identity['user'].user_id 
     target.created_by = id 

def updated_by(mapper, connection, target): 
    identity = request.environ.get('repoze.who.identity') 
    if identity: 
     id = identity['user'].user_id 
     target.updated_by = id 

from sqlalchemy.ext.declarative import declared_attr 
from sqlalchemy.ext.declarative import has_inherited_table 

class TestMixin(DeclarativeBase): 
    __tablename__ = 'TestMixin' 

    id = Column(Integer, autoincrement=True, primary_key=True) 

event.listen(TestMixin, 'before_insert', created_by) 
event.listen(TestMixin, 'before_update', updated_by) 

class MyClass(TestMixin): 
    __tablename__ = 'MyClass' 
    __mapper_args__ = {'concrete':True} 

    id = Column(Integer, autoincrement=True, primary_key=True) 

    created_by = Column(Integer, ForeignKey('user.user_id', 
         onupdate="cascade", ondelete="restrict")) 

    updated_by = Column(Integer, ForeignKey('user.user_id', 
         onupdate="cascade", ondelete="restrict")) 

Al agregar un nuevo objeto MiClase tengo created_by = Ninguno. Si creo event.listen para MyClass todo está bien. ¿Qué pasa?

+0

he encontrado la respuesta aquí http://stackoverflow.com/questions/12753450/ sqlalchemy-mixins-y-event-listener – uralbash

Respuesta

9

Heredar todos sus modelos de la clase base y suscribirse a esa clase base:

event.listen(MyBaseMixin, 'before_insert', get_created_by_id) 
event.listen(MyBaseMixin, 'before_update', get_updated_by_id) 

Ver más en Mixin and Custom Base Classes

+0

Este es mi código http://pastebin.com/vzsR5hde Estoy intentando usar Mixin pero obtengo un error: sqlalchemy.exc.InvalidRequestError: La tabla 'ttt' ya está definida para este Instancia de MetaData Especifique 'extend_existing = True' para redefinir opciones y columnas en un objeto Table existente. – uralbash

+0

@uralbash Su 'LogMixin' no es realmente una clase mix-in, sino una clase mapeada de" modelo ", ya que hereda de' DeclarativeBase'. Ahora mapea otra clase 'Net' que usa la misma tabla declarada, pero más columnas. –

+1

Esto no parece funcionar (¿ya?) En 0.9.6. SQLAlchemy me permitirá unir a un oyente a mi clase mixin base, pero nunca se llama al oyente. Si agrego el mismo oyente a una clase de modelo específico, se llama. (Y sí, es una clase mix-in real :)) – mmitchell

Cuestiones relacionadas