5

問題は、オブジェクトが新しい状態になったときにSQLAlchemyを使用して通知する方法がわからないことです。

SQLAlchemy ORM(宣言型)を使用してオブジェクトを更新しています:

class Customer(declarative_base()):

    __table_name__ = "customer"

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

オブジェクトがいつ状態に入るのか知りたい。特にUPDATEが発行された後、および状態が変化したとき。たとえばCustomer.status == 'registered'、以前は別の状態でした。

私は現在、'set'属性イベントでこれを行っています:

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)

その属性で「set」が呼び出されるたびにコードが起動し、valueoldvalueが異なるかどうかを確認します。問題は、targetパラメーターが完全に形成されていないため、まだすべての属性値が入力されていないことです。

これを行うためのより良い方法はありますか?ありがとう!

4

2 に答える 2

10

私の解決策は、'set'AttributeEventの代わりに'after_flush'SessionEventを使用することでした。

オブジェクトの値とoldvalueを具体的にチェックするサンプルSessionEventコードを提供してくれたagronholmに感謝します。

以下の解決策は、彼のコードを変更したものです。

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)

registry、キーがMapperPropertyであり、値がイベントハンドラーであるディクショナリです。 session、、、およびはすべてsqlalchemyのクラスおよび関数ですeventinspectobject_mapper

于 2013-03-27T23:37:26.893 に答える
2

before_updateイベントまたはbefore_flushイベントを使用して、後で発生するこれをインターセプトします。

于 2013-03-27T16:54:53.020 に答える