Python / SQLAlchemy:事件监听器after_flush触发十进制值,即使值没有改变

时间:2014-05-14 21:00:18

标签: python sqlalchemy

这是我的方法:

def member_field_change_after_flush(session, flush_context):
    """
    Keep track of MemberField objects changing per-session.
    """
    member_fields = field_changes[session]
    session_member_fields = filter(
        lambda model: isinstance(model, MemberField),
        session.new | session.dirty | session.deleted
    )

    for member_field in session_member_fields:
        for mapper_property in object_mapper(member_field).iterate_properties:
            if isinstance(mapper_property, ColumnProperty):
                attribute_state = inspect(member_field).attrs.get(mapper_property.key)
                history = attribute_state.history
                if history.has_changes():
                    member_fields[member_field.field_id] = {
                        'member_id': member_field.member_id,
                        'old_value': history.deleted[0] if history.deleted else None,
                        'new_value': attribute_state.value,
                        'field_type': member_field.field.ref_field_type.column_key,
                        'account_id': member_field.account_id,
                    }

如果我将数据库中的值从100.2改为100.2,则SQLAlchemy会认为某个值实际已更改并在history.deleted[0]属性中记录dict 1}}上面。

我对Python很新,所以我不确定如何解决这个问题。

1 个答案:

答案 0 :(得分:1)

每当更改某个值时,您的事件都会被触发。但是,要检查值是否实际更改,您需要调用session.is_modified(...)

示例:

for obj in session.dirty:
    # Here, the field might have been set to the same value
    if session.is_modified(obj):
        # Here, the fields value has actually changed

我想以这种方式实现这一点的原因是优化。 docs say something similar

  

is_modified(实例,include_collections = True,被动= True)

     

它实际上是在Session.dirty集合中检查给定实例的更昂贵和准确的版本;执行每个属性的净“脏”状态的完整测试。