2013-03-26 32 views
5

Vấn đề là tôi không thể tìm ra cách sử dụng SQLAlchemy để thông báo cho tôi khi một đối tượng đi vào trạng thái mới.Làm cách nào để có được trạng thái trước của đối tượng SQLAlchemy ORM sau khi cập nhật db?

Tôi đang sử dụng SQLAlchemy ORM (Declarative) để cập nhật một đối tượng:

class Customer(declarative_base()): 

    __table_name__ = "customer" 

    id = Column(Integer, primary_key=True) 
    status = Column(String) 

Tôi muốn biết khi một đối tượng chuyển sang trạng thái. Đặc biệt sau khi một UPDATE đã được ban hành và khi nhà nước thay đổi. Ví dụ. Customer.status == 'registered' và trước đây nó có trạng thái khác.

tôi đang làm điều này với một sự kiện 'set' thuộc tính:

from sqlalchemy import event 
from model import Customer 

def on_set_attribute(target, value, oldvalue, initiator): 
    print target.status 
    print value 
    print oldvalue 

event.listen(
     Customer.status, 
     'set', 
     on_set_attribute, 
     propagate=True, 
     active_history=True) 

Mã của tôi bắn mỗi khi 'đặt' được gọi là trên thuộc tính đó, và tôi kiểm tra xem valueoldvalue là khác nhau. Vấn đề là thông số target chưa được tạo thành đầy đủ nên nó chưa có tất cả các giá trị thuộc tính.

Có cách nào tốt hơn để thực hiện việc này không? Cảm ơn!

Trả lời

10

Giải pháp của tôi là sử dụng SessionEvent 'after_flush' thay vì 'set' AttributeEvent.

Rất cám ơn đến agronholm, người đã cung cấp mã SessionEvent ví dụ cụ thể đã kiểm tra giá trị của đối tượng và giá trị cũ.

Các giải pháp dưới đây là một biến thể của mã của mình:

def get_old_value(attribute_state): 
    history = attribute_state.history 
    return history.deleted[0] if history.deleted else None 


def trigger_attribute_change_events(object_): 
    for mapper_property in object_mapper(object_).iterate_properties: 
     if isinstance(mapper_property, ColumnProperty): 
      key = mapper_property.key 
      attribute_state = inspect(object_).attrs.get(key) 
      history = attribute_state.history 

      if history.has_changes(): 
       value = attribute_state.value 
       # old_value is None for new objects and old value for dirty objects 
       old_value = get_old_value(attribute_state) 
       handler = registry.get(mapper_property) 
       if handler: 
        handler(object_, value, old_value) 


def on_after_flush(session, flush_context): 
    changed_objects = session.new.union(session.dirty) 
    for o in changed_objects: 
     trigger_attribute_change_events(o) 

event.listen(session, "after_flush", on_after_flush) 

Các registry là một cuốn từ điển có phím MapperProperty và có giá trị là xử lý sự kiện. session, event, inspectobject_mapper là tất cả các lớp và chức năng sqlalchemy.