2012-01-18 26 views
9

Tôi có các trường created_by và updated_by trong mỗi mô hình. Các trường này được tự động điền với sqlalchemy.event.listen (trước đây là MapperExtension). Đối với mỗi mô hình, tôi viết: SQLAlchemy "event.listen" cho tất cả các kiểu

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

Khi mô hình có nhiều mã trở nên xấu xí. Có thể áp dụng event.listen ngay lập tức cho tất cả các mô hình hay không?

UPD: Tôi đang cố gắng để làm như vậy:

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

Khi tôi thêm một MyClass mới phản đối tôi có created_by = None. Nếu tôi tạo event.listen cho MyClass tất cả là tốt. Chuyện gì vậy?

+0

Tôi tìm thấy câu trả lời ở đây http://stackoverflow.com/questions/12753450/ sqlalchemy-mixins-and-event-listener – uralbash

Trả lời

9

Kế thừa tất cả các mô hình của bạn từ các lớp cơ sở và đăng ký với lớp cơ sở:

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

Xem thêm về Mixin and Custom Base Classes

+0

Đây là mã của tôi http://pastebin.com/vzsR5hde Tôi đang cố gắng sử dụng Mixin nhưng gặp lỗi: sqlalchemy.exc.InvalidRequestError: Bảng 'ttt' đã được xác định cho điều này Ví dụ về MetaData. Chỉ định 'extend_existing = True' để xác định lại các tùy chọn và cột trên đối tượng Bảng hiện có. – uralbash

+0

@uralbash 'LogMixin' của bạn không thực sự là một lớp kết hợp, mà là một lớp" mô hình "được ánh xạ, vì nó kế thừa từ' DeclarativeBase'. Bây giờ bạn ánh xạ lớp 'Net' khác sử dụng cùng một bảng đã khai báo, nhưng có nhiều cột hơn. –

+1

Điều này dường như không hoạt động (nữa?) Trong 0.9.6. SQLAlchemy sẽ cho phép tôi ràng buộc một người nghe đến lớp mixin cơ sở của tôi, nhưng người nghe không bao giờ được gọi. Nếu tôi thêm cùng một người nghe vào một lớp mô hình cụ thể, nó sẽ được gọi. (Và có, đó là một lớp trộn thực tế trong :)) – mmitchell

Các vấn đề liên quan