SqlAlchemy 2.0 中文文件(十三)
原文:
docs.sqlalchemy.org/en/20/contents.html
事件和內部
原文:
docs.sqlalchemy.org/en/20/orm/extending.html
SQLAlchemy ORM 以及 Core 通常透過事件鉤子進行擴充套件。請務必檢視事件系統的使用。
-
ORM 事件
-
會話事件
-
對映器事件
-
例項事件
-
屬性事件
-
查詢事件
-
儀器事件
-
-
ORM 內部
-
AttributeState
-
CascadeOptions
-
ClassManager
-
ColumnProperty
-
Composite
-
CompositeProperty
-
AttributeEventToken
-
IdentityMap
-
InspectionAttr
-
InspectionAttrInfo
-
InstanceState
-
InstrumentedAttribute
-
LoaderCallableStatus
-
Mapped
-
MappedColumn
-
MapperProperty
-
MappedSQLExpression
-
InspectionAttrExtensionType
-
NotExtension
-
merge_result()
-
merge_frozen_result()
-
PropComparator
-
Relationship
-
RelationshipDirection
-
RelationshipProperty
-
SQLORMExpression
-
Synonym
-
SynonymProperty
-
QueryContext
-
QueryableAttribute
-
UOWTransaction
-
-
ORM 異常
-
ConcurrentModificationError
-
DetachedInstanceError
-
FlushError
-
LoaderStrategyException
-
NO_STATE
-
ObjectDeletedError
-
ObjectDereferencedError
-
StaleDataError
-
UnmappedClassError
-
UnmappedColumnError
-
UnmappedError
-
UnmappedInstanceError
-
ORM 事件
原文:
docs.sqlalchemy.org/en/20/orm/events.html
ORM 包括各種可供訂閱的鉤子。
要了解最常用的 ORM 事件的介紹,請參閱使用事件跟蹤查詢、物件和會話更改部分。一般討論事件系統,請參閱事件。關於連線和低階語句執行等非 ORM 事件的描述,請參閱核心事件。
會話事件
最基本的事件鉤子可在 ORM Session
物件級別使用。這裡攔截的內容包括:
-
持久化操作 - 將更改傳送到資料庫的 ORM 重新整理過程可以使用在重新整理的不同部分觸發的事件進行擴充套件,以增強或修改傳送到資料庫的資料,或者在持久化發生時允許其他事情發生。在持久化事件中瞭解更多資訊。
-
物件生命週期事件 - 當物件被新增、持久化、從會話中刪除時觸發的鉤子。在物件生命週期事件中瞭解更多資訊。
-
執行事件 - 2.0 風格執行模型的一部分,攔截所有針對 ORM 實體的 SELECT 語句,以及在重新整理過程之外的批次 UPDATE 和 DELETE 語句,使用
Session.execute()
方法透過SessionEvents.do_orm_execute()
方法。在執行事件中瞭解更多關於此事件的資訊。
請務必閱讀使用事件跟蹤查詢、物件和會話更改章節,以瞭解這些事件的背景。
物件名稱 | 描述 |
---|---|
SessionEvents | 定義特定於Session 生命週期的事件。 |
class sqlalchemy.orm.SessionEvents
定義特定於Session
生命週期的事件。
例如:
from sqlalchemy import event
from sqlalchemy.orm import sessionmaker
def my_before_commit(session):
print("before commit!")
Session = sessionmaker()
event.listen(Session, "before_commit", my_before_commit)
listen()
函式將接受Session
物件,以及sessionmaker()
和scoped_session()
的返回結果。
此外,它接受Session
類,該類將全域性應用監聽器到所有Session
例項。
引數:
-
raw=False
–當為 True 時,傳遞給適用於單個物件的事件偵聽器函式的“target”引數將是例項的
InstanceState
管理物件,而不是對映的例項本身。版本 1.3.14 中的新功能。
-
restore_load_context=False
–適用於
SessionEvents.loaded_as_persistent()
事件。在事件鉤子完成時恢復物件的載入器上下文,以便正在進行的急切載入操作繼續正確地針對物件。如果在此事件中將物件移動到新的載入器上下文而未設定此標誌,則會發出警告。版本 1.3.14 中的新功能。
成員
after_attach(), after_begin(), after_bulk_delete(), after_bulk_update(), after_commit(), after_flush(), after_flush_postexec(), after_rollback(), after_soft_rollback(), after_transaction_create(), after_transaction_end(), before_attach(), before_commit(), before_flush(), deleted_to_detached(), deleted_to_persistent(), detached_to_persistent(), dispatch, do_orm_execute(), loaded_as_persistent(), pending_to_persistent(), pending_to_transient(), persistent_to_deleted(), persistent_to_detached(), persistent_to_transient(), transient_to_pending()
類簽名
類sqlalchemy.orm.SessionEvents
(sqlalchemy.event.Events
)
method after_attach(session: Session, instance: _O) → None
在例項附加到會話後執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_attach')
def receive_after_attach(session, instance):
"listen for the 'after_attach' event"
# ... (event handling logic) ...
這在新增、刪除或合併後呼叫。
注意
從 0.8 開始,此事件在專案完全與會話關聯之後觸發,這與以前的版本不同。對於需要物件尚未成為會話狀態的事件處理程式(例如,在目標物件尚未完成時可能自動重新整理的處理程式),請考慮新的before_attach()
事件。
另請參閱
SessionEvents.before_attach()
物件生命週期事件
method after_begin(session: Session, transaction: SessionTransaction, connection: Connection) → None
在連線上開始事務後執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_begin')
def receive_after_begin(session, transaction, connection):
"listen for the 'after_begin' event"
# ... (event handling logic) ...
注意
此事件在Session
修改其自身內部狀態的過程中呼叫。要在此掛鉤內呼叫 SQL 操作,請使用事件提供的Connection
;請勿直接使用Session
執行 SQL 操作。
引數:
-
session
– 目標Session
。 -
transaction
–SessionTransaction
。 -
connection
– 將用於 SQL 語句的Connection
物件。
另請參閱
SessionEvents.before_commit()
SessionEvents.after_commit()
SessionEvents.after_transaction_create()
SessionEvents.after_transaction_end()
method after_bulk_delete(delete_context: _O) → None
在呼叫傳統的Query.delete()
方法之後的事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_bulk_delete')
def receive_after_bulk_delete(delete_context):
"listen for the 'after_bulk_delete' event"
# ... (event handling logic) ...
# DEPRECATED calling style (pre-0.9, will be removed in a future release)
@event.listens_for(SomeSessionClassOrObject, 'after_bulk_delete')
def receive_after_bulk_delete(session, query, query_context, result):
"listen for the 'after_bulk_delete' event"
# ... (event handling logic) ...
從版本 0.9 開始更改:SessionEvents.after_bulk_delete()
事件現在接受引數SessionEvents.after_bulk_delete.delete_context
。將來的版本中將刪除接受上述“已棄用”引數簽名的監聽器函式的支援。
遺留特性
SessionEvents.after_bulk_delete()
方法是 SQLAlchemy 2.0 的傳統事件鉤子。該事件不參與使用delete()
在 ORM UPDATE and DELETE with Custom WHERE Criteria 中記錄的 2.0 風格呼叫。對於 2.0 風格的使用,SessionEvents.do_orm_execute()
鉤子將攔截這些呼叫。
引數:
delete_context -
一個包含有關更新的“刪除上下文”物件,包括這些屬性:
session
- 涉及的Session
。query
- 呼叫此更新操作的Query
物件。result
作為批次 DELETE 操作的結果返回的CursorResult
。
從版本 1.4 開始更改:update_context 不再與QueryContext
物件相關聯。
另請參閱
QueryEvents.before_compile_delete()
SessionEvents.after_bulk_update()
method after_bulk_update(update_context: _O) → None
在呼叫傳統Query.update()
方法之後的事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_bulk_update')
def receive_after_bulk_update(update_context):
"listen for the 'after_bulk_update' event"
# ... (event handling logic) ...
# DEPRECATED calling style (pre-0.9, will be removed in a future release)
@event.listens_for(SomeSessionClassOrObject, 'after_bulk_update')
def receive_after_bulk_update(session, query, query_context, result):
"listen for the 'after_bulk_update' event"
# ... (event handling logic) ...
從版本 0.9 開始更改:SessionEvents.after_bulk_update()
事件現在接受引數SessionEvents.after_bulk_update.update_context
。將來的版本中將刪除接受上述“已棄用”引數簽名的監聽器函式的支援。
遺留特性
SessionEvents.after_bulk_update()
方法是 SQLAlchemy 2.0 版本之後的傳統事件鉤子。該事件不參與使用update()
進行的 2.0 風格呼叫,該呼叫在 ORM UPDATE and DELETE with Custom WHERE Criteria 中有記錄。對於 2.0 風格的使用,SessionEvents.do_orm_execute()
鉤子將攔截這些呼叫。
引數:
update_context –
包含有關更新的“更新上下文”物件,包括這些屬性:
session
- 涉及的Session
query
-呼叫此更新操作的Query
物件。values
傳遞給Query.update()
的“值”字典。result
作為批次更新操作的結果返回的CursorResult
。
從 1.4 版本開始更改:update_context 不再與QueryContext
物件關聯。
另請參閱
QueryEvents.before_compile_update()
SessionEvents.after_bulk_delete()
method after_commit(session: Session) → None
在提交後執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_commit')
def receive_after_commit(session):
"listen for the 'after_commit' event"
# ... (event handling logic) ...
注意
SessionEvents.after_commit()
鉤子不是每次重新整理一次,也就是說,Session
可以在事務範圍內多次向資料庫發出 SQL。要攔截這些事件,請使用SessionEvents.before_flush()
、SessionEvents.after_flush()
或SessionEvents.after_flush_postexec()
事件。
注意
當呼叫SessionEvents.after_commit()
事件時,Session
處於非活動事務狀態,因此無法發出 SQL。若要發出與每個事務對應的 SQL,請使用SessionEvents.before_commit()
事件。
引數:
session – 目標Session
。
另請參閱
SessionEvents.before_commit()
SessionEvents.after_begin()
SessionEvents.after_transaction_create()
SessionEvents.after_transaction_end()
method after_flush(session: Session, flush_context: UOWTransaction) → None
在重新整理完成後執行,但在呼叫提交之前執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_flush')
def receive_after_flush(session, flush_context):
"listen for the 'after_flush' event"
# ... (event handling logic) ...
請注意,會話的狀態仍處於預重新整理狀態,即‘new’、‘dirty’和‘deleted’列表仍然顯示預重新整理狀態,以及例項屬性的歷史設定。
警告
此事件在Session
發出 SQL 以修改資料庫後,但在修改其內部狀態以反映這些更改之前執行,包括將新插入的物件放入標識對映中。在此事件中發出的 ORM 操作(如載入相關專案)可能會產生新的標識對映條目,這些條目將立即被替換,有時會導致令人困惑的結果。從版本 1.3.9 開始,SQLAlchemy 將為此條件發出警告。
引數:
-
session
– 目標Session
。 -
flush_context
– 處理重新整理詳細資訊的內部UOWTransaction
物件。
另請參閱
SessionEvents.before_flush()
SessionEvents.after_flush_postexec()
永續性事件
method after_flush_postexec(session: Session, flush_context: UOWTransaction) → None
在重新整理完成後執行,並在後執行狀態發生後執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_flush_postexec')
def receive_after_flush_postexec(session, flush_context):
"listen for the 'after_flush_postexec' event"
# ... (event handling logic) ...
這將是‘new’、‘dirty’和‘deleted’列表處於最終狀態的時刻。實際是否提交()取決於重新整理是否啟動了自己的事務或參與了較大事務。
引數:
-
session
– 目標Session
。 -
flush_context
– 處理重新整理細節的內部UOWTransaction
物件。
另請參閱
SessionEvents.before_flush()
SessionEvents.after_flush()
永續性事件
method after_rollback(session: Session) → None
在真正的 DBAPI 回滾發生後執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_rollback')
def receive_after_rollback(session):
"listen for the 'after_rollback' event"
# ... (event handling logic) ...
請注意,此事件僅在實際資料庫回滾發生時觸發 - 當底層 DBAPI 事務已經回滾時,並不會在每次呼叫 Session.rollback()
方法時觸發。在許多情況下,在此事件期間,Session
不會處於“活動”狀態,因為當前事務無效。要獲取在最外層回滾已經執行後處於活動狀態的 Session
,請使用 SessionEvents.after_soft_rollback()
事件,並檢查 Session.is_active
標誌。
引數:
session – 目標 Session
。
method after_soft_rollback(session: Session, previous_transaction: SessionTransaction) → None
在發生任何回滾之後執行,包括“軟”回滾,這些回滾實際上不會在 DBAPI 級別發出。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_soft_rollback')
def receive_after_soft_rollback(session, previous_transaction):
"listen for the 'after_soft_rollback' event"
# ... (event handling logic) ...
這對應於巢狀和外部回滾,即呼叫 DBAPI 的 rollback() 方法的最內層回滾,以及僅彈出事務堆疊的封閉回滾呼叫。
給定的 Session
可以在外部回滾後透過首先檢查 Session.is_active
標誌來呼叫 SQL 和 Session.query()
操作。
@event.listens_for(Session, "after_soft_rollback")
def do_something(session, previous_transaction):
if session.is_active:
session.execute(text("select * from some_table"))
引數:
-
session
– 目標Session
。 -
previous_transaction
– 剛關閉的SessionTransaction
事務標記物件。給定Session
的當前SessionTransaction
可透過Session.transaction
屬性獲得。
method after_transaction_create(session: Session, transaction: SessionTransaction) → None
在建立新的SessionTransaction
時執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_transaction_create')
def receive_after_transaction_create(session, transaction):
"listen for the 'after_transaction_create' event"
# ... (event handling logic) ...
此事件與SessionEvents.after_begin()
不同,因為它針對每個SessionTransaction
整體而發生,而不是在單個資料庫連線上開始事務時發生。它還針對巢狀事務和子事務進行呼叫,並且始終與相應的SessionEvents.after_transaction_end()
事件匹配(假設Session
的正常操作)。
引數:
-
session
– 目標Session
。 -
transaction
–目標
SessionTransaction
。要檢測是否為最外層的
SessionTransaction
,而不是“子事務”或 SAVEPOINT,請測試SessionTransaction.parent
屬性是否為None
:@event.listens_for(session, "after_transaction_create") def after_transaction_create(session, transaction): if transaction.parent is None: # work with top-level transaction
要檢測
SessionTransaction
是否為 SAVEPOINT,請使用SessionTransaction.nested
屬性:@event.listens_for(session, "after_transaction_create") def after_transaction_create(session, transaction): if transaction.nested: # work with SAVEPOINT transaction
另請參閱
SessionTransaction
SessionEvents.after_transaction_end()
method after_transaction_end(session: Session, transaction: SessionTransaction) → None
當一個SessionTransaction
的跨度結束時執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_transaction_end')
def receive_after_transaction_end(session, transaction):
"listen for the 'after_transaction_end' event"
# ... (event handling logic) ...
此事件與SessionEvents.after_commit()
不同,因為它對所有正在使用的SessionTransaction
物件進行對應,包括巢狀事務和子事務,並且始終與相應的SessionEvents.after_transaction_create()
事件匹配。
引數:
-
session
– 目標Session
。 -
transaction
–目標
SessionTransaction
。要檢測這是否是最外層的
SessionTransaction
,而不是“子事務”或 SAVEPOINT,請測試SessionTransaction.parent
屬性是否為None
:@event.listens_for(session, "after_transaction_create") def after_transaction_end(session, transaction): if transaction.parent is None: # work with top-level transaction
要檢測
SessionTransaction
是否為 SAVEPOINT,請使用SessionTransaction.nested
屬性:@event.listens_for(session, "after_transaction_create") def after_transaction_end(session, transaction): if transaction.nested: # work with SAVEPOINT transaction
另請參見
SessionTransaction
SessionEvents.after_transaction_create()
method before_attach(session: Session, instance: _O) → None
在將例項附加到會話之前執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'before_attach')
def receive_before_attach(session, instance):
"listen for the 'before_attach' event"
# ... (event handling logic) ...
這在新增、刪除或合併導致物件成為會話的一部分之前被呼叫。
另請參見
SessionEvents.after_attach()
物件生命週期事件
method before_commit(session: Session) → None
在提交之前執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'before_commit')
def receive_before_commit(session):
"listen for the 'before_commit' event"
# ... (event handling logic) ...
注意
SessionEvents.before_commit()
掛鉤不是每次重新整理一次,也就是說,在事務範圍內,Session
可以多次向資料庫發出 SQL。要攔截這些事件,請使用SessionEvents.before_flush()
、SessionEvents.after_flush()
或SessionEvents.after_flush_postexec()
事件。
引數:
session – 目標Session
。
另請參閱
SessionEvents.after_commit()
SessionEvents.after_begin()
SessionEvents.after_transaction_create()
SessionEvents.after_transaction_end()
method before_flush(session: Session, flush_context: UOWTransaction, instances: Sequence[_O] | None) → None
在重新整理過程開始之前執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'before_flush')
def receive_before_flush(session, flush_context, instances):
"listen for the 'before_flush' event"
# ... (event handling logic) ...
引數:
-
session
– 目標Session
。 -
flush_context
– 處理重新整理細節的內部UOWTransaction
物件。 -
instances
– 通常為None
,這是可以傳遞給Session.flush()
方法的物件集合(請注意,此用法已被棄用)。
另請參閱
SessionEvents.after_flush()
SessionEvents.after_flush_postexec()
永續性事件
method deleted_to_detached(session: Session, instance: _O) → None
攔截特定物件的“刪除到分離”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'deleted_to_detached')
def receive_deleted_to_detached(session, instance):
"listen for the 'deleted_to_detached' event"
# ... (event handling logic) ...
當一個被刪除的物件從會話中被驅逐時,觸發此事件。典型情況是當包含被刪除物件的Session
的事務被提交時;物件從被刪除狀態轉移到分離狀態。
當在呼叫Session.expunge_all()
或Session.close()
事件時,以及如果物件透過Session.expunge()
從其刪除狀態單獨清除時,也會為在重新整理時被刪除的物件呼叫。
另請參閱
物件生命週期事件
method deleted_to_persistent(session: Session, instance: _O) → None
攔截特定物件的“刪除到持久化”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'deleted_to_persistent')
def receive_deleted_to_persistent(session, instance):
"listen for the 'deleted_to_persistent' event"
# ... (event handling logic) ...
此轉換僅在成功重新整理後被刪除的物件由於呼叫Session.rollback()
而��恢復時發生。在任何其他情況下不會呼叫此事件。
另請參閱
物件生命週期事件
method detached_to_persistent(session: Session, instance: _O) → None
攔截特定物件的“分離到持久”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'detached_to_persistent')
def receive_detached_to_persistent(session, instance):
"listen for the 'detached_to_persistent' event"
# ... (event handling logic) ...
此事件是 SessionEvents.after_attach()
事件的一種特化,僅在此特定轉換時呼叫。通常在 Session.add()
呼叫期間以及在物件之前與 Session
不相關聯的情況下呼叫 Session.delete()
呼叫(請注意,將物件標記為“已刪除”在重新整理進行之前仍保持“持久”狀態)。
注意
如果物件在呼叫 Session.delete()
的過程中變為持久物件,則在呼叫此事件時物件尚未標記為已刪除。要檢測已刪除的物件,請在重新整理進行後檢查傳送到 SessionEvents.persistent_to_detached()
事件的 deleted
標誌,或者如果需要在重新整理之前攔截已刪除的物件,則在 SessionEvents.before_flush()
事件中檢查 Session.deleted
集合。
引數:
-
session
– 目標Session
-
instance
– 正在操作的 ORM 對映例項。
另請參閱
物件生命週期事件
attribute dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.SessionEventsDispatch object>
參考 _Dispatch 類。
雙向與 _Dispatch._events
method do_orm_execute(orm_execute_state: ORMExecuteState) → None
攔截代表 ORM Session
物件執行的語句執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'do_orm_execute')
def receive_do_orm_execute(orm_execute_state):
"listen for the 'do_orm_execute' event"
# ... (event handling logic) ...
此事件適用於從Session.execute()
方法以及相關方法如Session.scalars()
和Session.scalar()
呼叫的所有頂級 SQL 語句。從 SQLAlchemy 1.4 開始,透過Session.execute()
方法以及相關方法Session.scalars()
、Session.scalar()
等執行的所有 ORM 查詢都將參與此事件。此事件鉤子不適用於在 ORM 重新整理過程內部發出的查詢,即在重新整理中描述的過程。
注意
SessionEvents.do_orm_execute()
事件鉤子僅在ORM 語句執行時觸發,意味著僅對透過Session.execute()
等方法在Session
物件上呼叫的語句觸發。它不適用於僅由 SQLAlchemy Core 呼叫的語句,即透過Connection.execute()
直接呼叫或由Engine
物件發起而不涉及任何Session
的語句。要攔截所有SQL 執行,無論是否使用 Core 或 ORM API,請參閱ConnectionEvents
中的事件鉤子,例如ConnectionEvents.before_execute()
和ConnectionEvents.before_cursor_execute()
。
此事件鉤子也不適用於在 ORM 重新整理過程內部發出的查詢,即在重新整理中描述的過程;要攔截重新整理過程中的步驟,請參閱 Persistence Events 以及 Mapper-level Flush Events 中描述的事件鉤子。
此事件是一個do_
事件,意味著它具有替換Session.execute()
方法通常執行的操作的能力。這包括分片和結果快取方案,這些方案可能希望在多個資料庫連線上呼叫相同的語句,返回從每個連線合並的結果,或者根本不呼叫該語句,而是從快取返回資料。
該鉤子旨在替換在 SQLAlchemy 1.4 之前可以被子類化的Query._execute_and_instances
方法的使用。
引數:
orm_execute_state – 一個ORMExecuteState
的例項,其中包含有關當前執行的所有資訊,以及用於推導其他常見所需資訊的輔助函式。有關詳細資訊,請參閱該物件。
另請參閱
執行事件 - 如何使用SessionEvents.do_orm_execute()
的頂級文件
ORMExecuteState
- 傳遞給SessionEvents.do_orm_execute()
事件的物件,其中包含有關要呼叫的語句的所有資訊。它還提供了一個介面來擴充套件當前語句、選項和引數,以及一個選項,允許在任何時候以程式設計方式呼叫該語句。
ORM 查詢事件 - 包括使用SessionEvents.do_orm_execute()
的示例
Dogpile 快取 - 一個示例,演示如何將 Dogpile 快取與 ORM Session
整合,利用SessionEvents.do_orm_execute()
事件鉤子。
水平分片 - 水平分片示例/擴充套件依賴於SessionEvents.do_orm_execute()
事件鉤子,在多個後端上呼叫 SQL 語句並返回合併結果。
1.4 版中的新功能。
method loaded_as_persistent(session: Session, instance: _O) → None
攔截特定物件的“載入為永續性”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'loaded_as_persistent')
def receive_loaded_as_persistent(session, instance):
"listen for the 'loaded_as_persistent' event"
# ... (event handling logic) ...
此事件在 ORM 載入過程中呼叫,與InstanceEvents.load()
事件非常類似。但是,在這裡,事件可連結到Session
類或例項,而不是到對映器或類層次結構,並且與其他會話生命週期事件平滑整合。在呼叫此事件時,保證物件存在於會話的標識對映中。
注意
此事件在載入程式過程中呼叫,此時可能尚未完成渴望的載入器,並且物件的狀態可能不完整。此外,在物件上呼叫行級重新整理操作將使物件進入新的載入器上下文,從而干擾現有的載入上下文。請參閱InstanceEvents.load()
中有關使用SessionEvents.restore_load_context
引數的說明,該引數的工作方式與InstanceEvents.restore_load_context
相同,以解決此場景。
引數:
-
session
– 目標Session
-
instance
– 正在操作的 ORM 對映例項。
另請參閱
物件生命週期事件
method pending_to_persistent(session: Session, instance: _O) → None
攔截特定物件的“待定到持久”的轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'pending_to_persistent')
def receive_pending_to_persistent(session, instance):
"listen for the 'pending_to_persistent' event"
# ... (event handling logic) ...
此事件在重新整理過程中呼叫,類似於掃描Session.new
集合在SessionEvents.after_flush()
事件中。但是,在這種情況下,當呼叫事件時,物件已經被移動到持久狀態。
引數:
-
session
– 目標Session
-
instance
– 正在操作的 ORM 對映例項。
另請參閱
物件生命週期事件
method pending_to_transient(session: Session, instance: _O) → None
攔截特定物件的“待定到瞬態”的轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'pending_to_transient')
def receive_pending_to_transient(session, instance):
"listen for the 'pending_to_transient' event"
# ... (event handling logic) ...
當尚未重新整理的待定物件從會話中移除時,會發生這種較少見的轉換;這可能發生在Session.rollback()
方法回滾事務時,或者當使用Session.expunge()
方法時。
引數:
-
session
– 目標Session
-
instance
– 正在操作的 ORM 對映例項。
另請參見
物件生命週期事件
method persistent_to_deleted(session: Session, instance: _O) → None
攔截特定物件的“持久到已刪除”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'persistent_to_deleted')
def receive_persistent_to_deleted(session, instance):
"listen for the 'persistent_to_deleted' event"
# ... (event handling logic) ...
當在 flush 過程中從資料庫中刪除持久化物件的標識時,會觸發此事件,但是物件仍然與Session
相關聯,直到事務完成。
如果事務回滾,則物件再次轉移到持久狀態,並呼叫 SessionEvents.deleted_to_persistent()
事件。如果事務提交,則物件變為分離狀態,這將觸發 SessionEvents.deleted_to_detached()
事件。
請注意,雖然 Session.delete()
方法是將物件標記為已刪除的主要公共介面,但由於級聯規則的存在,許多物件會因級聯規則而被刪除,這些規則直到 flush 時才確定。因此,在 flush 進行之前,沒有辦法捕獲每個將要刪除的物件。因此,在 flush 結束時會呼叫 SessionEvents.persistent_to_deleted()
事件。
另請參見
物件生命週期事件
method persistent_to_detached(session: Session, instance: _O) → None
攔截特定物件的“持久到分離”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'persistent_to_detached')
def receive_persistent_to_detached(session, instance):
"listen for the 'persistent_to_detached' event"
# ... (event handling logic) ...
當持久化物件從會話中驅逐時,將會觸發此事件。導致此情況發生的條件有很多,包括:
-
使用
Session.expunge()
或Session.close()
等方法 -
在物件屬於該會話事務的 INSERT 語句的一部分時,呼叫
Session.rollback()
方法
引數:
-
session
– 目標Session
-
instance
– 正在操作的 ORM 對映例項。 -
deleted
– 布林值。如果為 True,則表示此物件因標記為已刪除並被 flush 而轉移到分離狀態。
另請參見
物件生命週期事件
method persistent_to_transient(session: Session, instance: _O) → None
攔截特定物件的“持久到瞬時”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'persistent_to_transient')
def receive_persistent_to_transient(session, instance):
"listen for the 'persistent_to_transient' event"
# ... (event handling logic) ...
當已重新整理的掛起物件從會話中被逐出時,發生了這種不太常見的轉換;這可能發生在 Session.rollback()
方法回滾事務時。
引數:
-
session
– 目標Session
-
instance
– 正在操作的 ORM 對映例項。
另請參閱
物件生命週期事件
method transient_to_pending(session: Session, instance: _O) → None
捕獲特定物件的“瞬態到掛起”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'transient_to_pending')
def receive_transient_to_pending(session, instance):
"listen for the 'transient_to_pending' event"
# ... (event handling logic) ...
此事件是 SessionEvents.after_attach()
事件的一種特化,僅在此特定轉換時呼叫。它通常在 Session.add()
呼叫期間被呼叫。
引數:
-
session
– 目標Session
-
instance
– 正在操作的 ORM 對映例項。
另請參閱
物件生命週期事件
對映器事件
對映器事件掛鉤涵蓋與單個或多個 Mapper
物件相關的事情,這些物件是將使用者定義的類對映到 Table
物件的中心配置物件。在 Mapper
級別發生的型別包括:
-
每個物件的永續性操作 - 最常見的對映器鉤子是工作單元鉤子,例如
MapperEvents.before_insert()
、MapperEvents.after_update()
等。這些事件與更粗粒度的會話級事件(例如SessionEvents.before_flush()
)形成對比,因為它們在重新整理過程中以每個物件為基礎發生;雖然物件上的更細粒度的活動更為直接,但Session
功能的可用性有限。 -
Mapper 配置事件 - 另一個主要的對映器鉤子類別是在類被對映時發生的事件,當對映器被完成時以及當對映器集合被配置為相互引用時。這些事件包括
MapperEvents.instrument_class()
、MapperEvents.before_mapper_configured()
和MapperEvents.mapper_configured()
在單個Mapper
級別,以及MapperEvents.before_configured()
和MapperEvents.after_configured()
在一組Mapper
物件的級別。
物件名稱 | 描述 |
---|---|
MapperEvents | 定義特定於對映的事件。 |
class sqlalchemy.orm.MapperEvents
定義特定於對映的事件。
例如(e.g.):
from sqlalchemy import event
def my_before_insert_listener(mapper, connection, target):
# execute a stored procedure upon INSERT,
# apply the value to the row to be inserted
target.calculated_value = connection.execute(
text("select my_special_function(%d)" % target.special_number)
).scalar()
# associate the listener function with SomeClass,
# to execute during the "before_insert" hook
event.listen(
SomeClass, 'before_insert', my_before_insert_listener)
可用的目標包括:
-
對映的類(mapped classes)
-
已對映或待對映類的未對映超類(使用
propagate=True
標誌) -
Mapper
物件 -
Mapper
類本身指示監聽所有對映器。
對映器事件提供了對對映器的關鍵部分的鉤子,包括與物件工具、物件載入和物件永續性相關的部分。特別是,永續性方法 MapperEvents.before_insert()
和 MapperEvents.before_update()
是增強正在持久化狀態的流行位置 - 但是,這些方法在幾個重要限制下執行。鼓勵使用者評估 SessionEvents.before_flush()
和 SessionEvents.after_flush()
方法,作為更靈活和使用者友好的掛鉤,在重新整理期間應用額外的資料庫狀態。
在使用 MapperEvents
時,listen()
函式提供了幾個修飾符。
引數(Parameters):
-
propagate=False
– 當為 True 時,事件監聽器應應用於所有繼承對映器和/或繼承類的對映器,以及任何作為此監聽器目標的對映器。 -
raw=False
– 當為 True 時,傳遞給適用事件監聽器函式的“target”引數將是例項的InstanceState
管理物件,而不是對映例項本身。 -
retval=False
–當為 True 時,使用者定義的事件函式必須具有返回值,其目的是控制後續事件傳播,或以其他方式透過對映器改變正在進行的操作。可能的返回值包括:
-
sqlalchemy.orm.interfaces.EXT_CONTINUE
- 正常繼續事件處理。 -
sqlalchemy.orm.interfaces.EXT_STOP
- 取消鏈中所有後續事件處理程式。 -
其他值 - 特定監聽器指定的返回值。
-
成員
after_configured(), after_delete(), after_insert(), after_mapper_constructed(), after_update(), before_configured(), before_delete(), before_insert(), before_mapper_configured(), before_update(), dispatch, instrument_class(), mapper_configured()
類簽名
類sqlalchemy.orm.MapperEvents
(sqlalchemy.event.Events
)
method after_configured() → None
被稱為一系列對映器已配置完成後。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'after_configured')
def receive_after_configured():
"listen for the 'after_configured' event"
# ... (event handling logic) ...
每次呼叫MapperEvents.after_configured()
事件時,都會在configure_mappers()
函式完成其工作後呼叫該事件。通常情況下,當對映首次被使用時,以及每當新的對映器可用並檢測到新的對映器使用時,會自動呼叫configure_mappers()
。
與MapperEvents.mapper_configured()
事件相比,該事件在配置操作進行時基於每個對映器呼叫;與該事件不同,當呼叫此事件時,所有交叉配置(例如反向引用)也將為任何待定的對映器提供。還與MapperEvents.before_configured()
進行對比,該事件在系列對映器配置之前被呼叫。
此事件僅適用於Mapper
類,而不適用於單個對映或對映類。它僅對所有對映作為一個整體呼叫:
from sqlalchemy.orm import Mapper
@event.listens_for(Mapper, "after_configured")
def go():
# ...
理論上,此事件每個應用程式呼叫一次,但實際上每當新對映器受到configure_mappers()
呼叫的影響時都會呼叫。如果在已經使用現有對映之後構建新對映,則可能會再次呼叫此事件。為確保特定事件僅被呼叫一次且不再呼叫,可以應用once=True
引數(自 0.9.4 版起新增):
from sqlalchemy.orm import mapper
@event.listens_for(mapper, "after_configured", once=True)
def go():
# ...
另請參見
MapperEvents.before_mapper_configured()
MapperEvents.mapper_configured()
MapperEvents.before_configured()
method after_delete(mapper: Mapper[_O], connection: Connection, target: _O) → None
在發出與該例項對應的 DELETE 語句後接收一個物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'after_delete')
def receive_after_delete(mapper, connection, target):
"listen for the 'after_delete' event"
# ... (event handling logic) ...
注意
此事件僅適用於會話重新整理操作,不適用於 ORM-啟用的 INSERT、UPDATE 和 DELETE 語句中描述的 ORM DML 操作。要攔截 ORM DML 事件,請使用SessionEvents.do_orm_execute()
。
此事件用於在給定連線上發出額外的 SQL 語句,以及執行與刪除事件相關的應用程式特定的簿記。
該事件通常在一批相同類的物件的 DELETE 語句在先前步驟中一次性發出後被呼叫。
警告
對映級重新整理事件僅允許對僅限於操作的行本地屬性進行非常有限的操作,同時允許在給定的Connection
上發出任何 SQL。請完整閱讀對映級重新整理事件中關於使用這些方法的指南;通常,應優先使用SessionEvents.before_flush()
方法進行一般性的重新整理更改。
引數:
-
mapper
– 此事件的目標Mapper
。 -
connection
– 用於為此例項發出 DELETE 語句的Connection
。這為特定於此例項的目標資料庫上的當前事務提供了一個控制代碼。 -
target
– 被刪除的對映例項。如果事件配置為raw=True
,則這將是與例項關聯的InstanceState
狀態管理物件。
返回:
此事件不支援返回值。
另請參閱
永續性事件
method after_insert(mapper: Mapper[_O], connection: Connection, target: _O) → None
在發出對應例項的 INSERT 語句後,會收到一個物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'after_insert')
def receive_after_insert(mapper, connection, target):
"listen for the 'after_insert' event"
# ... (event handling logic) ...
注意
此事件僅適用於會話重新整理操作,不適用於描述在 ORM-啟用的 INSERT、UPDATE 和 DELETE 語句中的 ORM DML 操作。要攔截 ORM DML 事件,請使用SessionEvents.do_orm_execute()
。
此事件用於修改例項發生 INSERT 後的僅 Python 狀態,並在給定連線上發出附加的 SQL 語句。
在先前步驟中一次性發出它們的 INSERT 語句後,通常會為同一類的一批物件呼叫此事件。在極為罕見的情況下,如果這不是理想的情況,可以使用batch=False
配置Mapper
物件,這將導致例項批次被拆分為單個(效能較差)事件->持久化->事件步驟。
警告
僅允許在對映器級別重新整理事件上執行非常有限的操作,僅限於對正在操作的行本地屬性的操作,並允許在給定的Connection
上發出任何 SQL。請完全閱讀對映器級重新整理事件中的注意事項,以獲取有關使用這些方法的指南;通常,應優先使用SessionEvents.before_flush()
方法進行一般重新整理更改。
引數:
-
mapper
– 此事件的目標Mapper
。 -
connection
– 用於為此例項發出 INSERT 語句的Connection
。這提供了一個控制代碼到目標資料庫上的當前事務,該事務特定於此例項。 -
target
– 正在持久化的對映例項。如果事件配置為raw=True
,則這將是與例項關聯的InstanceState
狀態管理物件。
返回:
此事件不支援返回值。
另請參閱
永續性事件
method after_mapper_constructed(mapper: Mapper[_O], class_: Type[_O]) → None
當Mapper
完全構建完成時,接收一個類和對映器。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'after_mapper_constructed')
def receive_after_mapper_constructed(mapper, class_):
"listen for the 'after_mapper_constructed' event"
# ... (event handling logic) ...
此事件在Mapper
的初始建構函式完成後呼叫。這發生在MapperEvents.instrument_class()
事件之後,以及在Mapper
對其引數進行初始遍歷以生成其MapperProperty
物件集合之後,這些物件可透過Mapper.get_property()
方法和Mapper.iterate_properties
屬性訪問。
此事件與 MapperEvents.before_mapper_configured()
事件不同之處在於,它在 Mapper
的建構函式內部呼叫,而不是在 registry.configure()
程序內呼叫。目前,此事件是唯一適用於希望在構造此 Mapper
時建立其他對映類的處理程式的事件,這些對映類將在下次執行 registry.configure()
時成為同一配置步驟的一部分。
版本 2.0.2 中的新功能。
另請參閱
物件版本控制 - 一個示例,說明使用 MapperEvents.before_mapper_configured()
事件建立新的對映器以記錄物件的更改審計歷史。
method after_update(mapper: Mapper[_O], connection: Connection, target: _O) → None
在發出對應於該例項的 UPDATE 語句後接收物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'after_update')
def receive_after_update(mapper, connection, target):
"listen for the 'after_update' event"
# ... (event handling logic) ...
注意
此事件僅適用於 會話重新整理操作,並且不適用於在 ORM-Enabled INSERT、UPDATE 和 DELETE 語句 中描述的 ORM DML 操作。要攔截 ORM DML 事件,請使用 SessionEvents.do_orm_execute()
。
此事件用於在發生 UPDATE 後修改僅在 Python 中的例項狀態,以及在給定連線上發出額外的 SQL 語句。
此方法對所有標記為“髒”的例項進行呼叫,甚至對其列基屬性沒有淨變化 的例項,並且沒有進行 UPDATE 語句。當任何列基屬性的“設定屬性”操作被呼叫或任何集合被修改時,物件被標記為髒。如果在更新時,沒有列基屬性有任何淨變化,將不會發出 UPDATE 語句。這意味著傳送到 MapperEvents.after_update()
的例項不保證已發出 UPDATE 語句。
要檢測物件上基於列的屬性是否有淨變化,並因此導致 UPDATE 語句,請使用 object_session(instance).is_modified(instance, include_collections=False)
。
該事件通常在一系列相同類的物件的 UPDATE 語句一次性發出之後被呼叫。在極少數情況下,如果這不是期望的情況,那麼可以將 Mapper
配置為 batch=False
,這將導致例項批次被拆分為單個(效能較差)的事件->持久化->事件步驟。
警告
對映器級別的重新整理事件僅允許對僅限於正在操作的行的屬性執行非常有限的操作,以及允許在給定的 Connection
上發出任何 SQL。請完全閱讀 對映器級重新整理事件 備註中關於使用這些方法的指導原則;通常,應優先考慮使用 SessionEvents.before_flush()
方法進行通用重新整理更改。
引數:
-
mapper
– 此事件的目標Mapper
。 -
connection
– 用於為此例項發出 UPDATE 語句的Connection
。這提供了一個控制代碼到當前事務的目標資料庫,特定於這個例項。 -
target
– 正在持久化的對映例項。如果事件配置為raw=True
,那麼這將是與例項相關聯的InstanceState
狀態管理物件。
返回值:
此事件不支援返回值。
另請參閱
持久化事件
method before_configured() → None
在一系列對映器被配置之前呼叫。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'before_configured')
def receive_before_configured():
"listen for the 'before_configured' event"
# ... (event handling logic) ...
MapperEvents.before_configured()
事件在每次呼叫 configure_mappers()
函式時被呼叫,在該函式執行任何工作之前。
此事件僅可應用於 Mapper
類,而不是單個對映或對映類。它僅對所有對映作為整體呼叫:
from sqlalchemy.orm import Mapper
@event.listens_for(Mapper, "before_configured")
def go():
...
將此事件與 MapperEvents.after_configured()
進行對比,後者在一系列對映器配置完成後呼叫,以及 MapperEvents.before_mapper_configured()
和 MapperEvents.mapper_configured()
,這兩者都在每個對映器基礎上呼叫。
理論上,此事件每個應用程式呼叫一次,但實際上,任何時候新的對映器要受 configure_mappers()
呼叫影響時都會呼叫此事件。如果在使用現有對映器之後構造新對映,則可能會再次呼叫此事件。要確保特定事件僅被呼叫一次且不再呼叫,可以應用 once=True
引數(0.9.4 中新增):
from sqlalchemy.orm import mapper
@event.listens_for(mapper, "before_configured", once=True)
def go():
...
另請參閱
MapperEvents.before_mapper_configured()
MapperEvents.mapper_configured()
MapperEvents.after_configured()
method before_delete(mapper: Mapper[_O], connection: Connection, target: _O) → None
在發出與該例項對應的 DELETE 語句之前接收一個物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'before_delete')
def receive_before_delete(mapper, connection, target):
"listen for the 'before_delete' event"
# ... (event handling logic) ...
注意
此事件僅適用於會話重新整理操作,不適用於描述在 ORM 啟用的 INSERT、UPDATE 和 DELETE 語句中的 ORM DML 操作。要攔截 ORM DML 事件,請使用 SessionEvents.do_orm_execute()
。
此事件用於在給定連線上發出附加的 SQL 語句,以及執行與刪除事件相關的應用程式特定簿記。
在後續步驟中一次性發出一批相同類別物件的 DELETE 語句之前,通常會為這個事件呼叫一次。
警告
對映器級重新整理事件僅允許對僅針對正在操作的行的屬性進行非常有限的操作,以及允許在給定的 Connection
上發出任何 SQL。請務必完整閱讀 對映器級重新整理事件 中的註釋,以獲取有關使用這些方法的指導;通常情況下,應首選 SessionEvents.before_flush()
方法進行一般性的重新整理更改。
引數:
-
mapper
– 此事件的目標Mapper
。 -
connection
– 用於為此例項發出 DELETE 語句的Connection
。這提供了一個控制代碼到當前事務的目標資料庫,特定於此例項。 -
target
– 正在刪除的對映例項。如果事件配置為raw=True
,則這將是與例項相關聯的InstanceState
狀態管理物件。
返回:
此事件不支援返回值。
請參閱
永續性事件
method before_insert(mapper: Mapper[_O], connection: Connection, target: _O) → None
在發出與該例項對應的 INSERT 語句之前接收物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'before_insert')
def receive_before_insert(mapper, connection, target):
"listen for the 'before_insert' event"
# ... (event handling logic) ...
注意
此事件僅適用於會話重新整理操作,並不適用於描述在 ORM 啟用的 INSERT、UPDATE 和 DELETE 語句中的 ORM DML 操作。要攔截 ORM DML 事件,請使用SessionEvents.do_orm_execute()
。
此事件用於修改例項之前的本地、非物件相關屬性,並在給定的連線上發出附加 SQL 語句。
在稍後的步驟中,通常會為同一類物件的一批物件呼叫此事件,然後在一次性發出它們的 INSERT 語句之前。在極少數情況下,如果這不是所需的,可以使用Mapper
物件配置batch=False
,這將導致例項的批處理被分解為單個(效能較差的)事件->永續性->事件步驟。
警告
Mapper 級別的重新整理事件僅允許非常有限的操作,僅限於操作中的行本地屬性,並允許在給定的Connection
上發出任何 SQL。請完全閱讀Mapper 級別的重新整理事件中的注意事項,以獲取使用這些方法的指南;通常,應優先考慮SessionEvents.before_flush()
方法進行重新整理時的一般更改。
引數:
-
mapper
– 此事件的目標Mapper
。 -
connection
– 用於為此例項發出 INSERT 語句的Connection
。這提供了一個控制代碼進入目標資料庫上的當前事務,特定於此例項。 -
target
– 正在持久化的對映例項。如果事件配置為raw=True
,則這將是與例項關聯的InstanceState
狀態管理物件。
返回:
此事件不支援返回值。
另請參見
永續性事件
method before_mapper_configured(mapper: Mapper[_O], class_: Type[_O]) → None
在特定對映器配置之前呼叫。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'before_mapper_configured')
def receive_before_mapper_configured(mapper, class_):
"listen for the 'before_mapper_configured' event"
# ... (event handling logic) ...
此事件旨在允許在配置步驟中跳過特定的對映器,透過返回interfaces.EXT_SKIP
符號,該符號指示給configure_mappers()
呼叫,表明應跳過當前配置執行中的此特定對映器(或使用propagate=True
時的對映器層次結構)。當跳過一個或多個對映器時,"new mappers"標誌將保持設定,這意味著在使用對映器時將繼續呼叫configure_mappers()
函式,以繼續嘗試配置所有可用的對映器。
與其他配置級別事件相比,MapperEvents.before_configured()
、MapperEvents.after_configured()
和MapperEvents.mapper_configured()
,:meth;.MapperEvents.before_mapper_configured
事件在註冊時提供有意義的返回值,當使用retval=True
引數註冊時。
版本 1.3 中的新內容。
例如:
from sqlalchemy.orm import EXT_SKIP
Base = declarative_base()
DontConfigureBase = declarative_base()
@event.listens_for(
DontConfigureBase,
"before_mapper_configured", retval=True, propagate=True)
def dont_configure(mapper, cls):
return EXT_SKIP
另請參見
MapperEvents.before_configured()
MapperEvents.after_configured()
MapperEvents.mapper_configured()
method before_update(mapper: Mapper[_O], connection: Connection, target: _O) → None
在發出與該例項對應的 UPDATE 語句之前接收物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'before_update')
def receive_before_update(mapper, connection, target):
"listen for the 'before_update' event"
# ... (event handling logic) ...
注意
此事件僅適用於會話重新整理操作,不適用於在 ORM-啟用的 INSERT、UPDATE 和 DELETE 語句中描述的 ORM DML 操作。要攔截 ORM DML 事件,請使用SessionEvents.do_orm_execute()
。
此事件用於在更新發生之前修改例項上的本地、與物件無關的屬性,以及在給定連線上發出附加的 SQL 語句。
此方法將為所有標記為“髒”的例項呼叫,即使它們的基於列的屬性沒有淨變化。當對其基於列的屬性之一呼叫“設定屬性”操作或修改其任何集合時,物件將被標記為髒。如果在更新時,沒有基於列的屬性有任何淨變化,將不會發出 UPDATE 語句。這意味著將傳送到MapperEvents.before_update()
的例項不保證會發出 UPDATE 語句,儘管您可以透過修改屬性以存在值的淨變化來影響結果。
要檢測物件上的基於列的屬性是否有淨變化,並因此生成 UPDATE 語句,請使用 object_session(instance).is_modified(instance, include_collections=False)
。
在稍後的步驟中,通常會一次呼叫相同類的一批物件的此事件,然後發出它們的 UPDATE 語句。在極其罕見的情況下,如果這不是理想的情況,可以將Mapper
配置為 batch=False
,這將導致將例項批處理為單個(並且效能更差)事件->持久化->事件步驟。
警告
對映器級重新整理事件僅允許對僅限於正在操作的行的屬性進行非常有限的操作,同時允許在給定的Connection
上發出任何 SQL。 請務必閱讀對映器級重新整理事件中的注意事項,以獲取有關使用這些方法的指導;一般來說,應優先考慮SessionEvents.before_flush()
方法進行通用重新整理更改。
引數:
-
mapper
– 此事件的目標Mapper
。 -
connection
– 用於為此例項發出 UPDATE 語句的Connection
。這為當前事務提供了一個控制代碼,該事務針對與此例項特定相關的目標資料庫。 -
target
– 正在持久化的對映例項。如果事件配置為raw=True
,則這將是與例項關聯的InstanceState
狀態管理物件。
返回:
此事件不支援返回值。
另請參閱:
持久化事件
attribute dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.MapperEventsDispatch object>
回溯到 _Dispatch 類。
雙向關聯到 _Dispatch._events
method instrument_class(mapper: Mapper[_O], class_: Type[_O]) → None
當首次構建對映器時,尚未應用到對映類的儀器。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'instrument_class')
def receive_instrument_class(mapper, class_):
"listen for the 'instrument_class' event"
# ... (event handling logic) ...
此事件是對映器構造的最早階段。大多數對映器屬性尚未初始化。要在初始對映器構造中接收事件,其中提供了基本狀態,例如Mapper.attrs
集合,可能更好地選擇MapperEvents.after_mapper_constructed()
事件。
此偵聽器可以應用於整個Mapper
類,也可以應用於任何用作將要對映的類的基類(使用propagate=True
標誌):
Base = declarative_base()
@event.listens_for(Base, "instrument_class", propagate=True)
def on_new_class(mapper, cls_):
" ... "
引數:
-
mapper
– 此事件的目標是Mapper
。 -
class_
– 對映類。
另請參閱:
MapperEvents.after_mapper_constructed()
method mapper_configured(mapper: Mapper[_O], class_: Type[_O]) → None
在configure_mappers()
呼叫範圍內,特定對映器完成其自身配置時呼叫。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'mapper_configured')
def receive_mapper_configured(mapper, class_):
"listen for the 'mapper_configured' event"
# ... (event handling logic) ...
當MapperEvents.mapper_configured()
事件在configure_mappers()
函式透過當前未配置的對映器列表時遇到每個對映器時,將被呼叫。configure_mappers()
通常在對映首次使用時自動呼叫,以及每當新對映器可用並檢測到新的對映器使用時。
當事件被呼叫時,對映器應該處於其最終狀態,但不包括可能從其他對映器呼叫的反向引用;它們可能仍在配置操作中待處理。而透過 relationship.back_populates
引數配置的雙向關係將完全可用,因為這種關係樣式不依賴於其他可能尚未配置的對映器來知道它們的存在。
對於一個確保所有對映器都準備就緒的事件,包括僅在其他對映上定義的反向引用,使用 MapperEvents.after_configured()
事件;該事件僅在所有已知對映完全配置後才呼叫。
MapperEvents.mapper_configured()
事件,與 MapperEvents.before_configured()
或 MapperEvents.after_configured()
不同,對於每個對映器/類分別呼叫,且對映器本身被傳遞給事件。它也只對特定的對映器呼叫一次。因此,該事件對於一次僅在特定對映器基礎上受益的配置步驟非常有用,不要求“backref”配置必須已準備好。
引數:
-
mapper
–Mapper
是此事件的目標。 -
class_
– 對映類。
另請參閱
MapperEvents.before_configured()
MapperEvents.after_configured()
MapperEvents.before_mapper_configured()
例項事件
例項事件專注於 ORM 對映例項的構造,包括當它們被例項化為瞬態物件時,當它們從資料庫載入併成為持久化物件時,以及當資料庫重新整理或物件上的過期操作發生時。
物件名稱 | 描述 |
---|---|
InstanceEvents | 定義了與物件生命週期特定的事件。 |
class sqlalchemy.orm.InstanceEvents
定義了與物件生命週期特定的事件。
例如:
from sqlalchemy import event
def my_load_listener(target, context):
print("on load!")
event.listen(SomeClass, 'load', my_load_listener)
可用的目標包括:
-
對映類
-
對映或將要對映的類的未對映超類(使用
propagate=True
標誌) -
Mapper
物件 -
Mapper
類本身指示監聽所有對映器。
例項事件與對映器事件密切相關,但更具體於例項及其儀器,而不是其永續性系統。
在使用InstanceEvents
時,listen()
函式提供了幾個修飾符。
引數:
-
propagate=False
– 當為 True 時,事件監聽器應該應用於所有繼承類��以及作為此監聽器目標的類。 -
raw=False
– 當為 True 時,傳遞給適用事件監聽器函式的“target”引數將是例項的InstanceState
管理物件,而不是對映例項本身。 -
restore_load_context=False
–適用於
InstanceEvents.load()
和InstanceEvents.refresh()
事件。在事件掛鉤完成時恢復物件的載入器上下文,以便持續的急切載入操作繼續適當地針對物件。如果未設定此標誌,並且在這些事件之一中將物件移動到新的載入器上下文,則會發出警告。自版本 1.3.14 起新增。
成員
dispatch, expire(), first_init(), init(), init_failure(), load(), pickle(), refresh(), refresh_flush(), unpickle()
類簽名
類sqlalchemy.orm.InstanceEvents
(sqlalchemy.event.Events
)
attribute dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.InstanceEventsDispatch object>
回溯到 _Dispatch 類。
雙向反對 _Dispatch._events
method expire(target: _O, attrs: Iterable[str] | None) → None
在某些屬性或其子集已過期後接收物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'expire')
def receive_expire(target, attrs):
"listen for the 'expire' event"
# ... (event handling logic) ...
‘keys’是屬性名稱列表。如果為 None,則整個狀態已過期。
引數:
-
target
– 對映例項。如果事件配置為raw=True
,則這將是與例項關聯的InstanceState
狀態管理物件。 -
attrs
– 已過期的屬性名稱序列,如果所有屬性都已過期,則為 None。
method first_init(manager: ClassManager[_O], cls: Type[_O]) → None
在呼叫特定對映的第一個例項時呼叫。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'first_init')
def receive_first_init(manager, cls):
"listen for the 'first_init' event"
# ... (event handling logic) ...
當為該特定類第一次呼叫__init__
方法時,呼叫此事件。事件在__init__
實際進行之前以及在呼叫InstanceEvents.init()
事件之前被呼叫。
method init(target: _O, args: Any, kwargs: Any) → None
在建構函式被呼叫時接收一個例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'init')
def receive_init(target, args, kwargs):
"listen for the 'init' event"
# ... (event handling logic) ...
這個方法只在物件的使用者空間構造期間呼叫,與物件的建構函式一起,例如它的__init__
方法。當物件從資料庫載入時不會呼叫它;請參見InstanceEvents.load()
事件以攔截資料庫載入。
事件在實際呼叫物件的__init__
建構函式之前被呼叫。kwargs
字典可以被就地修改,以影響傳遞給__init__
的內容。
引數:
-
target
– 對映的例項。如果事件配置為raw=True
,那麼這將是與例項關聯的InstanceState
狀態管理物件。 -
args
– 傳遞給__init__
方法的位置引數。這被傳遞為一個元組,目前是不可變的。 -
kwargs
– 傳遞給__init__
方法的關鍵字引數。這個結構可以被就地修改。
另請參見
InstanceEvents.init_failure()
InstanceEvents.load()
method init_failure(target: _O, args: Any, kwargs: Any) → None
在例項建構函式被呼叫並引發異常時接收一個例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'init_failure')
def receive_init_failure(target, args, kwargs):
"listen for the 'init_failure' event"
# ... (event handling logic) ...
這個方法只在物件的使用者空間構造期間呼叫,與物件的建構函式一起,例如它的__init__
方法。當物件從資料庫載入時不會呼叫它。
事件在__init__
方法引發異常後被呼叫。事件被呼叫後,原始異常被重新引發,以便物件的構造仍然引發異常。引發的實際異常和堆疊跟蹤應該存在於sys.exc_info()
中。
引數:
-
target
– 對映的例項。如果事件配置為raw=True
,那麼這將是與例項關聯的InstanceState
狀態管理物件。 -
args
– 傳遞給__init__
方法的位置引數。 -
kwargs
– 傳遞給__init__
方法的關鍵字引數。
另請參見
InstanceEvents.init()
InstanceEvents.load()
method load(target: _O, context: QueryContext) → None
在透過__new__
建立物件例項並進行初始屬性填充後接收物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'load')
def receive_load(target, context):
"listen for the 'load' event"
# ... (event handling logic) ...
這通常發生在基於傳入結果行建立例項時,並且僅在該例項的生命週期中呼叫一次。
警告
在結果行載入期間,當處理此例項接收到的第一行時,將呼叫此事件。當使用集合導向屬性進行急載入時,尚未發生要載入/處理的附加行,以便載入後續集合項。這既導致集合不會完全載入,也導致如果在此事件處理程式中發生操作,該操作會為物件發出另一個資料庫載入操作,則物件的“載入上下文”可能會發生變化並干擾現有的急載入器仍在進行中。
可能導致事件處理程式內“載入上下文”更改的示例包括但不限於:
-
訪問未包含在行中的延遲屬性將觸發“取消延遲”操作並重新整理物件
-
訪問聯合繼承子類上不屬於行的屬性將觸發重新整理操作。
從 SQLAlchemy 1.3.14 開始,當發生此情況時會發出警告。可以在事件上使用InstanceEvents.restore_load_context
選項來防止此警告;這將確保在呼叫事件後保持物件的現有載入上下文:
@event.listens_for(
SomeClass, "load", restore_load_context=True)
def on_load(instance, context):
instance.some_unloaded_attribute
從版本 1.3.14 開始更改:新增了InstanceEvents.restore_load_context
和SessionEvents.restore_load_context
標誌,適用於“載入”事件,確保在事件鉤子完成時恢復物件的載入上下文;如果物件的載入上下文在未設定此標誌的情況下發生更改,則會發出警告。
InstanceEvents.load()
事件也可以以類方法裝飾器的形式使用,稱為reconstructor()
。
引數:
-
target
– 對映例項。如果事件配置為raw=True
,則這將是與例項關聯的InstanceState
狀態管理物件。 -
context
– 與當前進行中的Query
對應的QueryContext
。如果載入不對應於Query
,例如在Session.merge()
期間,此引數可能為None
���
另請參閱
在載入過程中保持非對映狀態
InstanceEvents.init()
InstanceEvents.refresh()
SessionEvents.loaded_as_persistent()
method pickle(target: _O, state_dict: _InstanceDict) → None
在關聯狀態被 pickle 時接收一個物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'pickle')
def receive_pickle(target, state_dict):
"listen for the 'pickle' event"
# ... (event handling logic) ...
引數:
-
target
– 對映例項。如果事件配置為raw=True
,則這將是與例項關聯的InstanceState
狀態管理物件。 -
state_dict
– 由__getstate__
返回的包含要 pickle 的狀態的字典。
method refresh(target: _O, context: QueryContext, attrs: Iterable[str] | None) → None
在從查詢中重新整理一個或多個屬性後接收一個物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'refresh')
def receive_refresh(target, context, attrs):
"listen for the 'refresh' event"
# ... (event handling logic) ...
與InstanceEvents.load()
方法形成對比,該方法在物件首次從查詢中載入時被呼叫。
注意
在載入程式完成之前,此事件在載入程式程序中被呼叫,物件的狀態可能不完整。此外,在物件上呼叫行級重新整理操作將使物件進入新的載入程式上下文,干擾現有的載入上下文。有關如何使用InstanceEvents.restore_load_context
引數解決此情況的背景,請參閱有關InstanceEvents.load()
的註釋。
引數:
-
target
– 對映例項。如果事件配置為raw=True
,則這將是與例項關聯的InstanceState
狀態管理物件。 -
context
– 與當前進行中的Query
對應的QueryContext
。 -
attrs
– 已填充的屬性名稱序列,如果所有列對映的非延遲屬性都已填充,則為 None。
另請參閱
在載入時保持未對映狀態
InstanceEvents.load()
method refresh_flush(target: _O, flush_context: UOWTransaction, attrs: Iterable[str] | None) → None
在物件狀態持久化期間,接收一個包含一個或多個包含列級預設值或更新處理程式的屬性已被重新整理的物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'refresh_flush')
def receive_refresh_flush(target, flush_context, attrs):
"listen for the 'refresh_flush' event"
# ... (event handling logic) ...
這個事件與 InstanceEvents.refresh()
相同,只是在工作單元重新整理過程中呼叫,並且僅包括具有列級預設值或更新處理程式的非主鍵列,包括 Python 可呼叫物件以及可能透過 RETURNING 子句獲取的伺服器端預設值和觸發器。
注意
當 InstanceEvents.refresh_flush()
事件觸發時,對於一個被插入的物件以及一個被更新的物件,該事件主要針對更新過程;這主要是一個內部工件,指出插入動作也可以觸發此事件,注意插入行的主鍵列在此事件中被明確省略。為了攔截物件的新插入狀態,SessionEvents.pending_to_persistent()
和 MapperEvents.after_insert()
是更好的選擇。
引數:
-
target
– 對映例項。如果事件配置為raw=True
,則此處將是與例項關聯的InstanceState
狀態管理物件。 -
flush_context
– 處理重新整理細節的內部UOWTransaction
物件。 -
attrs
– 已填充的屬性名稱序列。
另請參閱
在載入時保持未對映狀態
獲取伺服器生成的預設值
列插入/更新預設值
method unpickle(target: _O, state_dict: _InstanceDict) → None
在相關聯的狀態被反序列化後,接收一個物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'unpickle')
def receive_unpickle(target, state_dict):
"listen for the 'unpickle' event"
# ... (event handling logic) ...
引數:
-
target
– 對映例項。如果事件配置為raw=True
,則此處將是與例項關聯的InstanceState
狀態管理物件。 -
state_dict
– 傳送到__setstate__
的字典,包含被序列化的狀態字典。
屬性事件
屬性事件在 ORM 對映物件的各個屬性發生時觸發。這些事件為諸如自定義驗證函式和反向引用處理程式等功能奠定了基礎。
另請參閱
更改屬性行為
物件名稱 | 描述 |
---|---|
屬性事件 | 定義物件屬性的事件。 |
class sqlalchemy.orm.AttributeEvents
定義物件屬性的事件。
這些通常在目標類的類繫結描述符上定義。
例如,要註冊一個將接收AttributeEvents.append()
事件的監聽器:
from sqlalchemy import event
@event.listens_for(MyClass.collection, 'append', propagate=True)
def my_append_listener(target, value, initiator):
print("received append event for target: %s" % target)
當AttributeEvents.retval
標誌傳遞給listen()
或listens_for()
時,監聽器可以選擇返回可能修改的值,如下所示,使用AttributeEvents.set()
事件進行說明:
def validate_phone(target, value, oldvalue, initiator):
"Strip non-numeric characters from a phone number"
return re.sub(r'\D', '', value)
# setup listener on UserContact.phone attribute, instructing
# it to use the return value
listen(UserContact.phone, 'set', validate_phone, retval=True)
像上面的驗證函式也可以引發異常,如ValueError
以停止操作。
當應用監聽器到具有對映子類的對映類時,AttributeEvents.propagate
標誌也很重要,例如在使用對映器繼承模式時:
@event.listens_for(MySuperClass.attr, 'set', propagate=True)
def receive_set(target, value, initiator):
print("value set: %s" % target)
下面是可用於listen()
和listens_for()
函式的修飾符的完整列表。
引數:
-
active_history=False
– 當為 True 時,表示“set”事件希望無條件地接收被替換的“舊”值,即使這需要觸發資料庫載入。請注意,active_history
也可以透過column_property()
和relationship()
直接設定。 -
propagate=False
– 當為 True 時,監聽器函式將不僅為給定的類屬性建立,還將為該類的所有當前子類以及該類的所有未來子類上具有相同名稱的屬性建立,使用一個額外的監聽器來監聽儀器事件。 -
raw=False
– 當為 True 時,事件的“target”引數將是InstanceState
管理物件,而不是對映例項本身。 -
retval=False
– 當為 True 時,使用者定義的事件監聽必須從函式中返回“value”引數。這使得監聽函式有機會更改最終用於“set”或“append”事件的值。
成員
append(), append_wo_mutation(), bulk_replace(), dispatch, dispose_collection(), init_collection(), init_scalar(), modified(), remove(), set()
類簽名
類 sqlalchemy.orm.AttributeEvents
(sqlalchemy.event.Events
)
method append(target: _O, value: _T, initiator: Event, *, key: EventConstants = EventConstants.NO_KEY) → _T | None
接收集合附加事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'append')
def receive_append(target, value, initiator):
"listen for the 'append' event"
# ... (event handling logic) ...
在每個元素被附加到集合時,都會呼叫附加事件。這適用於單個項的附加以及“批次替換”操作。
引數:
-
target
– 接收事件的物件例項。如果監聽器以raw=True
註冊,這將是InstanceState
物件。 -
value
– 被附加的值。如果此監聽器以retval=True
註冊,則監聽函式必須返回此值,或者替換它的新值。 -
initiator
– 表示事件啟動的Event
例項。可能會被後向引用處理程式修改以控制連結的事件傳播,以及被檢查以獲取有關事件源的資訊。 -
key
–當使用
AttributeEvents.include_key
引數設定為 True 來建立事件時,這將是操作中使用的鍵,例如collection[some_key_or_index] = value
。如果未使用AttributeEvents.include_key
設定事件,將根本不傳遞此引數給事件;這是為了允許與不包括key
引數的現有事件處理程式向後相容。版本 2.0 中的新功能。
返回:
如果事件以 retval=True
註冊,則應返回給定值或新的有效值。
另請參閱
AttributeEvents
- 關於監聽器選項的背景資訊,例如傳播到子類。
AttributeEvents.bulk_replace()
method append_wo_mutation(target: _O, value: _T, initiator: Event, *, key: EventConstants = EventConstants.NO_KEY) → None
接收集合附加事件,其中集合實際上未被改變。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'append_wo_mutation')
def receive_append_wo_mutation(target, value, initiator):
"listen for the 'append_wo_mutation' event"
# ... (event handling logic) ...
此事件與 AttributeEvents.append()
不同,因為它是為去重集合(如集合和字典)觸發的,當物件已存在於目標集合中時。該事件沒有返回值,並且給定物件的標識不能更改。
當集合已透過後向引用事件發生變異時,該事件用於將物件級聯到Session
中。
引數:
-
target
– 接收事件的物件例項。如果偵聽器以raw=True
註冊,這將是InstanceState
物件。 -
value
– 如果物件在集合中尚不存在,則將追加的值。 -
initiator
– 一個表示事件啟動的Event
例項。可以透過後向引用處理程式修改其原始值,以控制連結的事件傳播,也可以檢查有關事件源的資訊。 -
key
–當使用
AttributeEvents.include_key
引數設定為 True 建立事件時,這將是操作中使用的鍵,例如collection[some_key_or_index] = value
。如果未使用AttributeEvents.include_key
設定事件,根本不會將引數傳遞給事件;這是為了與不包含key
引數的現有事件處理程式向後相容。在版本 2.0 中新增。
返回:
沒有為此事件定義返回值。
在版本 1.4.15 中新增。
method bulk_replace(target: _O, values: Iterable[_T], initiator: Event, *, keys: Iterable[EventConstants] | None = None) → None
接收一個集合“批次替換”事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'bulk_replace')
def receive_bulk_replace(target, values, initiator):
"listen for the 'bulk_replace' event"
# ... (event handling logic) ...
此事件在作為 ORM 物件處理之前的批次集合設定操作的傳入值序列上被呼叫,可以在值被視為 ORM 物件之前就地修改。這是一個“早期掛鉤”,在批次替換例程嘗試協調哪些物件已經存在於集合中,哪些物件正在被淨替換操作移除之前執行。
通常情況下,此方法與AttributeEvents.append()
事件的使用結合。當同時使用這兩個事件時,請注意,批次替換操作將為所有新專案呼叫AttributeEvents.append()
事件,即使在為整個集合呼叫AttributeEvents.bulk_replace()
之後,也會呼叫AttributeEvents.append()
事件。為了確定AttributeEvents.append()
事件是否屬於批次替換,請使用符號attributes.OP_BULK_REPLACE
來測試傳入的 initiator:
from sqlalchemy.orm.attributes import OP_BULK_REPLACE
@event.listens_for(SomeObject.collection, "bulk_replace")
def process_collection(target, values, initiator):
values[:] = [_make_value(value) for value in values]
@event.listens_for(SomeObject.collection, "append", retval=True)
def process_collection(target, value, initiator):
# make sure bulk_replace didn't already do it
if initiator is None or initiator.op is not OP_BULK_REPLACE:
return _make_value(value)
else:
return value
版本 1.2 中的新內容。
引數:
-
target
– 接收事件的物件例項。如果監聽器註冊為raw=True
,這將是InstanceState
物件。 -
value
– 正在設定的值的序列(例如列表)。處理程式可以直接修改此列表。 -
initiator
– 代表事件啟動的Event
例項。 -
keys
–當使用
AttributeEvents.include_key
引數設定為 True 來建立事件時,這將是操作中使用的鍵序列,通常僅用於字典更新。如果未使用AttributeEvents.include_key
來設定事件,則根本不會將引數傳遞給事件;這是為了允許與不包括key
引數的現有事件處理程式保持向後相容性。版本 2.0 中的新內容。
另請參閱
AttributeEvents
- 關於監聽器選項的背景,例如傳播到子類。
attribute dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.AttributeEventsDispatch object>
參考回 _Dispatch 類。
雙向反對 _Dispatch._events
method dispose_collection(target: _O, collection: Collection[Any], collection_adapter: CollectionAdapter) → None
收到一個“collection dispose”事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'dispose_collection')
def receive_dispose_collection(target, collection, collection_adapter):
"listen for the 'dispose_collection' event"
# ... (event handling logic) ...
當集合被替換時,此事件將觸發基於集合的屬性,即:
u1.addresses.append(a1)
u1.addresses = [a2, a3] # <- old collection is disposed
舊集合將包含其先前的內容。
版本 1.2 中的更改:傳遞給AttributeEvents.dispose_collection()
的集合現在將在處理之前保持其內容;以前,集合將為空。
另請參閱
AttributeEvents
- 關於監聽器選項的背景,例如傳播到子類。
method init_collection(target: _O, collection: Type[Collection[Any]], collection_adapter: CollectionAdapter) → None
收到一個“collection init”事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'init_collection')
def receive_init_collection(target, collection, collection_adapter):
"listen for the 'init_collection' event"
# ... (event handling logic) ...
當為空屬性首次生成初始“空集合”時,以及當集合被替換為新集合時(例如透過設定事件),將觸發此事件。
例如,假設User.addresses
是基於關係的集合,事件在此處觸發:
u1 = User()
u1.addresses.append(a1) # <- new collection
在替換操作期間也會發生:
u1.addresses = [a2, a3] # <- new collection
引數:
-
target
– 接收事件的物件例項。如果監聽器以raw=True
註冊,這將是InstanceState
物件。 -
collection
– 新集合。這將始終從relationship.collection_class
指定的內容生成,並且始終為空。 -
collection_adapter
– 將調解對集合的內部訪問的CollectionAdapter
。
另請參閱
AttributeEvents
- 關於監聽器選項的背景,例如傳播到子類。
AttributeEvents.init_scalar()
- 此事件的“標量”版本。
method init_scalar(target: _O, value: _T, dict_: Dict[Any, Any]) → None
接收一個標量“init”事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'init_scalar')
def receive_init_scalar(target, value, dict_):
"listen for the 'init_scalar' event"
# ... (event handling logic) ...
當訪問未初始化的、未持久化的標量屬性時,例如讀取時,將呼叫此事件:
x = my_object.some_attribute
當未初始化屬性發生此事件時,ORM 的預設行為是返回值None
;請注意,這與 Python 通常引發AttributeError
的行為不同。此處的事件可用於自定義實際返回的值,假設事件監聽器將映象配置在 Core Column
物件上的預設生成器。
由於Column
上的預設生成器也可能產生像時間戳這樣的變化值,因此AttributeEvents.init_scalar()
事件處理程式也可用於設定新返回的值,以便 Core 級別的預設生成函式實際上只觸發一次,但在訪問非持久化物件上的屬性時。通常,當訪問未初始化屬性時,不會對物件的狀態進行任何更改(在較舊的 SQLAlchemy 版本中實際上會更改物件的狀態)。
如果列上的預設生成器返回特定常量,則可以使用處理程式如下:
SOME_CONSTANT = 3.1415926
class MyClass(Base):
# ...
some_attribute = Column(Numeric, default=SOME_CONSTANT)
@event.listens_for(
MyClass.some_attribute, "init_scalar",
retval=True, propagate=True)
def _init_some_attribute(target, dict_, value):
dict_['some_attribute'] = SOME_CONSTANT
return SOME_CONSTANT
在上面的示例中,我們將屬性MyClass.some_attribute
初始化為SOME_CONSTANT
的值。上述程式碼包括以下特性:
-
透過在給定的
dict_
中設定值SOME_CONSTANT
,我們表明這個值將被持久化到資料庫中。這取代了在Column
的預設生成器中使用SOME_CONSTANT
的方法。在屬性儀器化中給出的active_column_defaults.py
示例演示了對於變化的預設值使用相同方法的情況,例如時間戳生成器。在這個特定的例子中,這樣做並不是嚴格必要的,因為無論如何SOME_CONSTANT
都會成為 INSERT 語句的一部分。 -
透過建立
retval=True
標誌,我們從函式返回的值將被屬性獲取器返回。如果沒有這個標誌,事件被認為是被動觀察者,我們函式的返回值將被忽略。 -
如果對映類包括繼承的子類,則
propagate=True
標誌是重要的,這些子類也將使用此事件監聽器。如果沒有這個標誌,繼承的子類將不使用我們的事件處理程式。
在上面的例子中,當我們將我們的值應用到給定的dict_
時,屬性設定事件AttributeEvents.set()
以及由validates
提供的相關驗證功能都不會被呼叫。要使這些事件響應我們新生成的值,將該值應用到給定物件作為正常的屬性設定操作:
SOME_CONSTANT = 3.1415926
@event.listens_for(
MyClass.some_attribute, "init_scalar",
retval=True, propagate=True)
def _init_some_attribute(target, dict_, value):
# will also fire off attribute set events
target.some_attribute = SOME_CONSTANT
return SOME_CONSTANT
當設定了多個監聽器時,值的生成會從一個監聽器“鏈式”傳遞到下一個監聽器,透過將前一個指定retval=True
的監聽器返回的值作為下一個監聽器的value
引數傳遞。
引數:
-
target
– 接收事件的物件例項。如果監聽器註冊為raw=True
,這將是InstanceState
物件。 -
value
– 在此事件監聽器被呼叫之前要返回的值。這個值最初為None
,但是如果存在多個監聽器,則將是上一個事件處理程式函式的返回值。 -
dict_
– 此對映物件的屬性字典。這通常是物件的__dict__
,但在所有情況下都表示屬性系統用於訪問此屬性的實際值的目標。將值放入該字典中的效果是該值將在工作單元生成的 INSERT 語句中使用。
另請參閱
AttributeEvents.init_collection()
- 此事件的集合版本
AttributeEvents
- 關於監聽器選項的背景資訊,如傳播到子類。
屬性儀表化 - 參見 active_column_defaults.py
示例。
method modified(target: _O, initiator: Event) → None
接收一個‘修改’事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'modified')
def receive_modified(target, initiator):
"listen for the 'modified' event"
# ... (event handling logic) ...
當使用 flag_modified()
函式在未設定任何特定值的情況下觸發修改事件時,將觸發此事件。
1.2 版中的新內容。
引數:
-
target
– 接收事件的物件例項。如果監聽器使用raw=True
註冊,這將是InstanceState
物件。 -
initiator
– 一個代表事件啟動的Event
例項。
另請參閱
AttributeEvents
- 關於監聽器選項的背景,例如傳播到子類。
method remove(target: _O, value: _T, initiator: Event, *, key: EventConstants = EventConstants.NO_KEY) → None
接收一個集合移除事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'remove')
def receive_remove(target, value, initiator):
"listen for the 'remove' event"
# ... (event handling logic) ...
引數:
-
target
– 接收事件的物件例項。如果監聽器使用raw=True
註冊,這將是InstanceState
物件。 -
value
– 被移除的值。 -
initiator
– 一個代表事件啟動的Event
例項。可以透過 backref 處理程式修改其原始值,以控制鏈式事件傳播。 -
key
–當使用
AttributeEvents.include_key
引數設定為 True 建立事件時,這將是操作中使用的鍵,例如del collection[some_key_or_index]
。如果未使用AttributeEvents.include_key
設定事件,引數根本不會傳遞給事件;這是為了允許現有事件處理程式與不包含key
引數的事件處理程式向後相容。2.0 版中的新內容。
返回:
未為此事件定義返回值。
另請參閱
AttributeEvents
- 關於監聽器選項的背景,例如傳播到子類。
method set(target: _O, value: _T, oldvalue: _T, initiator: Event) → None
接收一個標量集合事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'set')
def receive_set(target, value, oldvalue, initiator):
"listen for the 'set' event"
# ... (event handling logic) ...
引數:
-
target
– 接收事件的物件例項。如果監聽器使用raw=True
註冊,這將是InstanceState
物件。 -
value
– 被設定的值。如果此監聽器使用retval=True
註冊,監聽器函式必須返回此值,或替換它的新值。 -
oldvalue
– 被替換的先前值。這也可以是符號NEVER_SET
或NO_VALUE
。如果監聽器使用active_history=True
註冊,當現有值當前未載入或過期時,將從資料庫載入屬性的先前值。 -
initiator
– 代表事件啟動的Event
例項。可能會被 backref 處理程式從其原始值修改,以控制鏈式事件傳播。
返回:
如果事件是以retval=True
註冊的,則應返回給定值或新的有效值。
另請參見
AttributeEvents
- 關於偵聽器選項的背景,例如傳播到子類。
查詢事件
物件名稱 | 描述 |
---|---|
QueryEvents | 代表在構建Query 物件時的事件。 |
class sqlalchemy.orm.QueryEvents
代表在構建Query
物件時的事件。
傳統特性
QueryEvents
事件方法在 SQLAlchemy 2.0 中已過時,僅適用於直接使用Query
物件。它們不適用於 2.0 風格語句。要攔截和修改 2.0 風格 ORM 使用的事件,請使用SessionEvents.do_orm_execute()
鉤子。
QueryEvents
鉤子現在已被SessionEvents.do_orm_execute()
事件鉤子取代。
成員
before_compile(), before_compile_delete(), before_compile_update(), dispatch
類簽名
類sqlalchemy.orm.QueryEvents
(sqlalchemy.event.Events
)
method before_compile(query: Query) → None
在核心Select
物件之前將Query
物件接收到。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeQuery, 'before_compile')
def receive_before_compile(query):
"listen for the 'before_compile' event"
# ... (event handling logic) ...
自版本 1.4 起棄用:QueryEvents.before_compile()
事件被更強大的SessionEvents.do_orm_execute()
鉤子所取代。在版本 1.4 中,QueryEvents.before_compile()
事件不再用於ORM 級別的屬性載入,例如延遲載入或過期屬性以及關係載入器的載入。請參閱 ORM 查詢事件中的新示例,展示了攔截和修改 ORM 查詢的新方法,最常見的目的是新增任意的過濾條件。
此事件旨在允許對查詢進行更改:
@event.listens_for(Query, "before_compile", retval=True)
def no_deleted(query):
for desc in query.column_descriptions:
if desc['type'] is User:
entity = desc['entity']
query = query.filter(entity.deleted == False)
return query
通常應該使用retval=True
引數監聽事件,以便修改後的查詢可以返回。
預設情況下,QueryEvents.before_compile()
事件將禁止“烘焙”查詢快取查詢,如果事件鉤子返回一個新的Query
物件。這影響了烘焙查詢擴充套件的直接使用以及它在關係的惰性載入器和急切載入器中的操作。為了重新建立被快取的查詢,請應用新增bake_ok
標誌的事件:
@event.listens_for(
Query, "before_compile", retval=True, bake_ok=True)
def my_event(query):
for desc in query.column_descriptions:
if desc['type'] is User:
entity = desc['entity']
query = query.filter(entity.deleted == False)
return query
當bake_ok
設定為 True 時,事件鉤子只會被呼叫一次,並且不會為正在被快取的特定查詢的後續呼叫而呼叫。
自版本 1.3.11 起新增:- 在QueryEvents.before_compile()
事件中新增了“bake_ok”標誌,並且如果未設定此標誌,則不允許透過“烘焙”擴充套件進行快取的事件處理程式返回一個新的Query
物件。
另請參閱
QueryEvents.before_compile_update()
QueryEvents.before_compile_delete()
使用 before_compile 事件
method before_compile_delete(query: Query, delete_context: BulkDelete) → None
允許對Query
物件進行修改,Query.delete()
內部。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeQuery, 'before_compile_delete')
def receive_before_compile_delete(query, delete_context):
"listen for the 'before_compile_delete' event"
# ... (event handling logic) ...
自版本 1.4 棄用:QueryEvents.before_compile_delete()
事件已被功能更強大的SessionEvents.do_orm_execute()
鉤取代。
類似於QueryEvents.before_compile()
事件,此事件應配置為retval=True
,並返回修改後的Query
物件,如下所示
@event.listens_for(Query, "before_compile_delete", retval=True)
def no_deleted(query, delete_context):
for desc in query.column_descriptions:
if desc['type'] is User:
entity = desc['entity']
query = query.filter(entity.deleted == False)
return query
引數:
-
query
– 一個Query
例項;這也是給定“刪除上下文”物件的.query
屬性。 -
delete_context
– 一個“刪除上下文”物件,與QueryEvents.after_bulk_delete.delete_context
中描述的物件型別相同。
新版本 1.2.17 中新增。
另請參閱
QueryEvents.before_compile()
QueryEvents.before_compile_update()
method before_compile_update(query: Query, update_context: BulkUpdate) → None
允許在Query.update()
內修改Query
物件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeQuery, 'before_compile_update')
def receive_before_compile_update(query, update_context):
"listen for the 'before_compile_update' event"
# ... (event handling logic) ...
自版本 1.4 棄用:QueryEvents.before_compile_update()
事件已被功能更強大的SessionEvents.do_orm_execute()
鉤取代。
類似於QueryEvents.before_compile()
事件,如果要用該事件來修改Query
物件,則應配置為retval=True
,並返回修改後的Query
物件,如下所示
@event.listens_for(Query, "before_compile_update", retval=True)
def no_deleted(query, update_context):
for desc in query.column_descriptions:
if desc['type'] is User:
entity = desc['entity']
query = query.filter(entity.deleted == False)
update_context.values['timestamp'] = datetime.utcnow()
return query
“更新上下文”物件的.values
字典也可以像上面示例的那樣就地修改。
引數:
-
query
– 一個Query
例項;這也是給定“更新上下文”物件的.query
屬性。 -
update_context
– 一個“更新上下文”物件,它與QueryEvents.after_bulk_update.update_context
中描述的物件相同。物件具有在 UPDATE 上下文中的.values
屬性,該屬性是傳遞給Query.update()
的引數字典。可以修改此字典以更改生成的 UPDATE 語句的 VALUES 子句。
1.2.17 版中的新內容。
另請參閱
QueryEvents.before_compile()
QueryEvents.before_compile_delete()
attribute dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.QueryEventsDispatch object>
參考回到 _Dispatch 類。
雙向針對 _Dispatch._events
儀器化事件
定義了 SQLAlchemy 的類儀器化系統。
這個模組通常對使用者應用程式不直接可見,但定義了 ORM 互動的大部分內容。
instrumentation.py 處理了終端使用者類的註冊以進行狀態跟蹤。它與分別建立了每個例項和每個類屬性儀器化的 state.py 和 attributes.py 密切互動。
類的儀器化系統可以使用sqlalchemy.ext.instrumentation
模組進行每個類或全域性基礎上的定製化,該模組提供了構建和指定替代儀器化形式的方法。
物件名稱 | 描述 |
---|---|
InstrumentationEvents | 與類儀器化事件相關的事件。 |
class sqlalchemy.orm.InstrumentationEvents
與類儀器化事件相關的事件。
這裡的監聽器支援對任何新風格類進行建立,即任何‘type’的子類物件。然後將為針對該類的事件觸發事件。如果傳遞了“propagate=True”標誌給 event.listen(),則該事件也將為該類的子類觸發。
Python 的 type
內建函式也被接受為目標,當使用時,將對所有類發出事件。
請注意,此處的“propagate”標誌預設為 True
,與其他類級別事件不同,後者的預設值為 False
。這意味著當在超類上建立偵聽器時,新的子類也將成為這些事件的主題。
成員
attribute_instrument(), class_instrument(), class_uninstrument(), dispatch
類簽名
類sqlalchemy.orm.InstrumentationEvents
(sqlalchemy.event.Events
)
method attribute_instrument(cls: ClassManager[_O], key: _KT, inst: _O) → None
當屬性被儀器化時呼叫。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeBaseClass, 'attribute_instrument')
def receive_attribute_instrument(cls, key, inst):
"listen for the 'attribute_instrument' event"
# ... (event handling logic) ...
method class_instrument(cls: ClassManager[_O]) → None
在給定類被儀器化之後呼叫。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeBaseClass, 'class_instrument')
def receive_class_instrument(cls):
"listen for the 'class_instrument' event"
# ... (event handling logic) ...
要獲取ClassManager
,請使用manager_of_class()
。
method class_uninstrument(cls: ClassManager[_O]) → None
在給定類被取消儀器化之前呼叫。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeBaseClass, 'class_uninstrument')
def receive_class_uninstrument(cls):
"listen for the 'class_uninstrument' event"
# ... (event handling logic) ...
要獲取ClassManager
,請使用manager_of_class()
。
attribute dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.InstrumentationEventsDispatch object>
參考 _Dispatch 類。
雙向對 _Dispatch._events
會話事件
最基本的事件鉤子可在 ORM Session
物件級別使用。在此攔截的內容包括:
-
持久化操作 - 將更改傳送到資料庫的 ORM 重新整理過程可以使用在重新整理的不同部分觸發的事件進行擴充套件,以增強或修改傳送到資料庫的資料,或者在持久化發生時允許其他事情發生。在持久化事件中瞭解更多資訊。
-
物件生命週期事件 - 當物件從會話中新增、持久化、刪除時觸發的鉤子。在物件生命週期事件中瞭解更多資訊。
-
執行事件 - 作為 2.0 風格執行模型的一部分,針對 ORM 實體的所有 SELECT 語句以及重新整理過程之外的批次 UPDATE 和 DELETE 語句都會被攔截,使用
Session.execute()
方法,並透過SessionEvents.do_orm_execute()
方法。在執行事件中瞭解更多資訊。
請務必閱讀使用事件跟蹤查詢、物件和會話更改章節,以瞭解這些事件的背景。
物件名稱 | 描述 |
---|---|
SessionEvents | 定義特定於Session 生命週期的事件。 |
class sqlalchemy.orm.SessionEvents
定義特定於Session
生命週期的事件。
例如:
from sqlalchemy import event
from sqlalchemy.orm import sessionmaker
def my_before_commit(session):
print("before commit!")
Session = sessionmaker()
event.listen(Session, "before_commit", my_before_commit)
listen()
函式將接受Session
物件,以及sessionmaker()
和scoped_session()
的返回結果。
此外,它接受Session
類,將全域性應用監聽器到所有Session
例項。
引數:
-
raw=False
–當為 True 時,傳遞給適用於單個物件的事件監聽器函式的“target”引數將是例項的
InstanceState
管理物件,而不是對映例項本身。新版本 1.3.14 中新增。
-
restore_load_context=False
–適用於
SessionEvents.loaded_as_persistent()
事件。在事件鉤子完成時恢復物件的載入器上下文,以便持續的急切載入操作繼續適當地針對物件。如果在此事件中將物件移動到新的載入器上下文而未設定此標誌,則會發出警告。新版本 1.3.14 中新增。
成員
after_attach(), after_begin(), after_bulk_delete(), after_bulk_update(), after_commit(), after_flush(), after_flush_postexec(), after_rollback(), after_soft_rollback(), after_transaction_create(), after_transaction_end(), before_attach(), before_commit(), before_flush(), deleted_to_detached(), deleted_to_persistent(), detached_to_persistent(), dispatch, do_orm_execute(), loaded_as_persistent(), pending_to_persistent(), pending_to_transient(), persistent_to_deleted(), persistent_to_detached(), persistent_to_transient(), transient_to_pending()
類簽名
類sqlalchemy.orm.SessionEvents
(sqlalchemy.event.Events
)
method after_attach(session: Session, instance: _O) → None
在例項被附加到會話之後執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_attach')
def receive_after_attach(session, instance):
"listen for the 'after_attach' event"
# ... (event handling logic) ...
在新增、刪除或合併後呼叫。
注意
自 0.8 版開始,此事件在專案完全與會話相關聯之後觸發,這與之前的版本不同。對於需要物件尚未成為會話狀態的事件處理程式(例如,當目標物件尚未完全完成時可能自動重新整理的處理程式),請考慮使用新的before_attach()
事件。
另請參見
SessionEvents.before_attach()
物件生命週期事件
method after_begin(session: Session, transaction: SessionTransaction, connection: Connection) → None
在連線上啟動事務後執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_begin')
def receive_after_begin(session, transaction, connection):
"listen for the 'after_begin' event"
# ... (event handling logic) ...
注意
此事件在Session
修改其自身內部狀態的過程中呼叫。在此掛鉤內呼叫 SQL 操作,請使用事件提供的Connection
;不要直接使用Session
執行 SQL 操作。
引數:
-
session
– 目標Session
。 -
transaction
–SessionTransaction
。 -
connection
– 將用於 SQL 語句的Connection
物件。
另請參見
SessionEvents.before_commit()
SessionEvents.after_commit()
SessionEvents.after_transaction_create()
SessionEvents.after_transaction_end()
method after_bulk_delete(delete_context: _O) → None
當傳統的Query.delete()
方法被呼叫後的事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_bulk_delete')
def receive_after_bulk_delete(delete_context):
"listen for the 'after_bulk_delete' event"
# ... (event handling logic) ...
# DEPRECATED calling style (pre-0.9, will be removed in a future release)
@event.listens_for(SomeSessionClassOrObject, 'after_bulk_delete')
def receive_after_bulk_delete(session, query, query_context, result):
"listen for the 'after_bulk_delete' event"
# ... (event handling logic) ...
從版本 0.9 開始更改:SessionEvents.after_bulk_delete()
事件現在接受引數SessionEvents.after_bulk_delete.delete_context
。將來版本中將刪除接受上述“已棄用”的先前引數簽名的偵聽器函式的支援。
舊特性
從 SQLAlchemy 2.0 開始,SessionEvents.after_bulk_delete()
方法是一箇舊的事件鉤子。該事件不參與使用delete()
在 ORM UPDATE and DELETE with Custom WHERE Criteria 中記錄的 2.0 風格呼叫。對於 2.0 風格的使用,SessionEvents.do_orm_execute()
鉤子將攔截這些呼叫。
引數:
delete_context -
一個包含有關更新的“刪除上下文”物件,包括以下屬性:
session
- 參與的Session
。query
- 呼叫此更新操作的Query
物件。result
- 作為批次刪除操作的結果返回的CursorResult
。
從版本 1.4 開始:update_context 不再與QueryContext
物件相關聯。
另請參閱
QueryEvents.before_compile_delete()
SessionEvents.after_bulk_update()
method after_bulk_update(update_context: _O) → None
用於在呼叫舊的Query.update()
方法之後觸發事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_bulk_update')
def receive_after_bulk_update(update_context):
"listen for the 'after_bulk_update' event"
# ... (event handling logic) ...
# DEPRECATED calling style (pre-0.9, will be removed in a future release)
@event.listens_for(SomeSessionClassOrObject, 'after_bulk_update')
def receive_after_bulk_update(session, query, query_context, result):
"listen for the 'after_bulk_update' event"
# ... (event handling logic) ...
從版本 0.9 開始更改:SessionEvents.after_bulk_update()
事件現在接受引數SessionEvents.after_bulk_update.update_context
。將來版本中將刪除接受上述“已棄用”的先前引數簽名的偵聽器函式的支援。
舊特性
SessionEvents.after_bulk_update()
方法是 SQLAlchemy 2.0 中的一箇舊式事件鉤子。此事件不參與使用 update()
進行 2.0 風格呼叫的文件化操作。要使用 2.0 風格,SessionEvents.do_orm_execute()
鉤子將攔截這些呼叫。
引數:
update_context -
包含關於更新的“更新上下文”物件,包括這些屬性:
session
- 涉及的Session
。query
- 呼叫此更新操作的Query
物件。values
- 傳遞給Query.update()
的values
字典。result
- 作為批次更新操作的結果返回的CursorResult
。
從版本 1.4 起更改:update_context 不再與QueryContext
物件關聯。
另請參閱
QueryEvents.before_compile_update()
SessionEvents.after_bulk_delete()
method after_commit(session: Session) → None
在提交之後執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_commit')
def receive_after_commit(session):
"listen for the 'after_commit' event"
# ... (event handling logic) ...
注
SessionEvents.after_commit()
鉤子不是每次重新整理都執行的,也就是說,在事務的範圍內,Session
可以多次向資料庫發出 SQL。要攔截這些事件,可以使用 SessionEvents.before_flush()
、SessionEvents.after_flush()
或 SessionEvents.after_flush_postexec()
事件。
注
當 SessionEvents.after_commit()
事件被呼叫時,Session
處於非活動事務狀態,因此無法發出 SQL。要發出與每個事務對應的 SQL,請使用 SessionEvents.before_commit()
事件。
引數:
session – 目標 Session
。
請參見
SessionEvents.before_commit()
SessionEvents.after_begin()
SessionEvents.after_transaction_create()
SessionEvents.after_transaction_end()
method after_flush(session: Session, flush_context: UOWTransaction) → None
在 flush 完成後執行,但在提交之前呼叫。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_flush')
def receive_after_flush(session, flush_context):
"listen for the 'after_flush' event"
# ... (event handling logic) ...
注意,會話的狀態仍然處於 pre-flush 狀態,即'new'、'dirty'和'deleted'列表仍然顯示 pre-flush 狀態以及例項屬性上的歷史設定。
警告
此事件在 Session
發出 SQL 修改資料庫之後執行,但在它修改內部狀態以反映這些更改之前執行,包括將新插入的物件放入標識對映中。在此事件內發出的 ORM 操作(如載入相關專案)可能會產生新的標識對映條目,這些條目將立即被替換,有時會導致混淆的結果。從版本 1.3.9 起,SQLAlchemy 會對此條件發出警告。
引數:
-
session
– 目標Session
。 -
flush_context
– 處理 flush 細節的內部UOWTransaction
物件。
請參見
SessionEvents.before_flush()
SessionEvents.after_flush_postexec()
永續性事件
method after_flush_postexec(session: Session, flush_context: UOWTransaction) → None
在 flush 完成後執行,並在 post-exec 狀態發生後執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_flush_postexec')
def receive_after_flush_postexec(session, flush_context):
"listen for the 'after_flush_postexec' event"
# ... (event handling logic) ...
這將是'new'、'dirty'和'deleted'列表處於最終狀態的時候。實際的 commit() 可能已經發生,也可能沒有發生,這取決於 flush 是否啟動了自己的事務或者參與了更大的事務。
引數:
-
session
– 目標Session
。 -
flush_context
– 處理重新整理細節的內部UOWTransaction
物件。
另請參見
SessionEvents.before_flush()
SessionEvents.after_flush()
永續性事件
method after_rollback(session: Session) → None
在實際發生 DBAPI 回滾後執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_rollback')
def receive_after_rollback(session):
"listen for the 'after_rollback' event"
# ... (event handling logic) ...
請注意,此事件僅在實際對資料庫執行回滾時觸發 - 如果底層 DBAPI 事務已經被回滾,則不會每次呼叫Session.rollback()
方法時都觸發。在許多情況下,Session
在此事件期間將不處於“活動”狀態,因為當前事務無效。要在最外層回滾進行後獲取一個活動的Session
,請使用SessionEvents.after_soft_rollback()
事件,並檢查Session.is_active
標誌。
引數:
session – 目標Session
。
method after_soft_rollback(session: Session, previous_transaction: SessionTransaction) → None
在發生任何回滾後執行,包括“軟”回滾,這種回滾在 DBAPI 級別實際上不會發出。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_soft_rollback')
def receive_after_soft_rollback(session, previous_transaction):
"listen for the 'after_soft_rollback' event"
# ... (event handling logic) ...
這對應於巢狀和外部回滾,即呼叫 DBAPI 的 rollback()方法的最內部回滾,以及僅從事務堆疊中彈出自身的封閉回滾呼叫。
給定的Session
可以用於在外部回滾後透過首先檢查Session.is_active
標誌來呼叫 SQL 和Session.query()
操作:
@event.listens_for(Session, "after_soft_rollback")
def do_something(session, previous_transaction):
if session.is_active:
session.execute(text("select * from some_table"))
引數:
-
session
– 目標Session
。 -
previous_transaction
– 剛剛關閉的SessionTransaction
事務標記物件。給定Session
的當前SessionTransaction
可以透過Session.transaction
屬性獲得。
method after_transaction_create(session: Session, transaction: SessionTransaction) → None
當建立新的SessionTransaction
時執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_transaction_create')
def receive_after_transaction_create(session, transaction):
"listen for the 'after_transaction_create' event"
# ... (event handling logic) ...
此事件與SessionEvents.after_begin()
不同,因為它針對每個SessionTransaction
總體發生,而不是在個別資料庫連線上開始事務時發生。它還用於巢狀事務和子事務,並始終與相應的SessionEvents.after_transaction_end()
事件匹配(假設Session
正常執行)。
引數:
-
session
– 目標Session
。 -
transaction
–目標
SessionTransaction
。要檢測此是否為最外層
SessionTransaction
,而不是“子事務”或 SAVEPOINT,請測試SessionTransaction.parent
屬性是否為None
:@event.listens_for(session, "after_transaction_create") def after_transaction_create(session, transaction): if transaction.parent is None: # work with top-level transaction
要檢測
SessionTransaction
是否為 SAVEPOINT,請使用SessionTransaction.nested
屬性:@event.listens_for(session, "after_transaction_create") def after_transaction_create(session, transaction): if transaction.nested: # work with SAVEPOINT transaction
另請參閱
SessionTransaction
SessionEvents.after_transaction_end()
method after_transaction_end(session: Session, transaction: SessionTransaction) → None
當SessionTransaction
的跨度結束時執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'after_transaction_end')
def receive_after_transaction_end(session, transaction):
"listen for the 'after_transaction_end' event"
# ... (event handling logic) ...
此事件與SessionEvents.after_commit()
不同,它對應於所有正在使用的SessionTransaction
物件,包括巢狀事務和子事務,並且始終與相應的SessionEvents.after_transaction_create()
事件匹配。
引數:
-
session
– 目標Session
。 -
transaction
–目標
SessionTransaction
。要檢測是否為最外層的
SessionTransaction
,而不是“子事務”或 SAVEPOINT,請測試SessionTransaction.parent
屬性是否為None
:@event.listens_for(session, "after_transaction_create") def after_transaction_end(session, transaction): if transaction.parent is None: # work with top-level transaction
要檢測
SessionTransaction
是否為 SAVEPOINT,請使用SessionTransaction.nested
屬性:@event.listens_for(session, "after_transaction_create") def after_transaction_end(session, transaction): if transaction.nested: # work with SAVEPOINT transaction
另請參閱
SessionTransaction
SessionEvents.after_transaction_create()
method before_attach(session: Session, instance: _O) → None
在例項附加到會話之前執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'before_attach')
def receive_before_attach(session, instance):
"listen for the 'before_attach' event"
# ... (event handling logic) ...
在新增、刪除或合併導致物件成為會話的一部分之前呼叫此方法。
另請參閱
SessionEvents.after_attach()
物件生命週期事件
method before_commit(session: Session) → None
在呼叫提交之前執行。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'before_commit')
def receive_before_commit(session):
"listen for the 'before_commit' event"
# ... (event handling logic) ...
注意
SessionEvents.before_commit()
掛鉤不是每次重新整理的,也就是說,在事務範圍內,Session
可以多次向資料庫發出 SQL。要攔截這些事件,請使用SessionEvents.before_flush()
、SessionEvents.after_flush()
或SessionEvents.after_flush_postexec()
事件。
引數:
session – 目標Session
。
另請參閱
SessionEvents.after_commit()
SessionEvents.after_begin()
SessionEvents.after_transaction_create()
SessionEvents.after_transaction_end()
method before_flush(session: Session, flush_context: UOWTransaction, instances: Sequence[_O] | None) → None
在重新整理過程開始之前執��。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'before_flush')
def receive_before_flush(session, flush_context, instances):
"listen for the 'before_flush' event"
# ... (event handling logic) ...
引數:
-
session
– 目標Session
。 -
flush_context
– 處理重新整理細節的內部UOWTransaction
物件。 -
instances
– 通常為None
,這是可以傳遞給Session.flush()
方法的物件集合(請注意,此用法已被棄用)。
另請參閱
SessionEvents.after_flush()
SessionEvents.after_flush_postexec()
永續性事件
method deleted_to_detached(session: Session, instance: _O) → None
攔截特定物件的“刪除到分離”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'deleted_to_detached')
def receive_deleted_to_detached(session, instance):
"listen for the 'deleted_to_detached' event"
# ... (event handling logic) ...
當從會話中刪除的物件被驅逐時,將呼叫此事件。典型情況是當刪除物件的會話的事務被提交時發生;物件從刪除狀態移動到分離狀態。
還會為在呼叫Session.expunge_all()
或Session.close()
事件時被刪除的物件呼叫,以及如果物件透過Session.expunge()
從其刪除狀態單獨驅逐。
另請參閱
物件生命週期事件
method deleted_to_persistent(session: Session, instance: _O) → None
攔截特定物件的“刪除到持久”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'deleted_to_persistent')
def receive_deleted_to_persistent(session, instance):
"listen for the 'deleted_to_persistent' event"
# ... (event handling logic) ...
僅當在重新整理中成功刪除的物件由於呼叫Session.rollback()
而被恢復時,才會發生此轉換。在任何其他情況下不會呼叫該事件。
另請參閱
物件生命週期事件
method detached_to_persistent(session: Session, instance: _O) → None
攔截特定物件的“分離到持久化”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'detached_to_persistent')
def receive_detached_to_persistent(session, instance):
"listen for the 'detached_to_persistent' event"
# ... (event handling logic) ...
此事件是 SessionEvents.after_attach()
事件的一個特化,僅針對此特定轉換呼叫。它通常在 Session.add()
呼叫期間呼叫,以及在物件之前未與 Session
關聯的情況下,在 Session.delete()
呼叫期間呼叫(請注意,標記為“已刪除”的物件在重新整理之前仍處於“持久化”狀態)。
注意
如果物件在呼叫 Session.delete()
時變為持久化物件,則在呼叫此事件時物件尚未標記為已刪除。要檢測已刪除的物件,請在重新整理後檢查傳送到 SessionEvents.persistent_to_detached()
事件的 deleted
標誌,或者在重新整理之前需要攔截已刪除物件時,在 SessionEvents.before_flush()
事件中檢查 Session.deleted
集合。
引數:
-
session
– 目標Session
-
instance
– 正在操作的 ORM 對映例項。
參見
物件生命週期事件
attribute dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.SessionEventsDispatch object>
參考回到 _Dispatch 類。
雙向對抗 _Dispatch._events
method do_orm_execute(orm_execute_state: ORMExecuteState) → None
攔截代表 ORM Session
物件執行的語句。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'do_orm_execute')
def receive_do_orm_execute(orm_execute_state):
"listen for the 'do_orm_execute' event"
# ... (event handling logic) ...
此事件被呼叫用於從Session.execute()
方法呼叫的所有頂級 SQL 語句,以及相關方法,如Session.scalars()
和Session.scalar()
。從 SQLAlchemy 1.4 開始,所有透過Session.execute()
方法執行的 ORM 查詢以及相關方法Session.scalars()
、Session.scalar()
等都將參與此事件。此事件掛鉤不適用於在 ORM 重新整理過程內部發出的查詢,即在重新整理中描述的過程。
注意
SessionEvents.do_orm_execute()
事件掛鉤僅針對 ORM 語句執行觸發,即透過Session.execute()
和類似方法在Session
物件上呼叫的語句。它不會觸發僅由 SQLAlchemy Core 呼叫的語句,即僅透過Connection.execute()
直接呼叫的語句或從不涉及任何Session
的Engine
物件發出的語句。要攔截所有SQL 執行,無論是否使用 Core 或 ORM API,請參見ConnectionEvents
中的事件掛鉤,如ConnectionEvents.before_execute()
和ConnectionEvents.before_cursor_execute()
。
此事件掛鉤不適用於在 ORM 重新整理過程內部發出的查詢,即在重新整理中描述的過程;要攔截重新整理過程中的步驟,請參見永續性事件以及對映器級重新整理事件中描述的事件掛鉤。
此事件是一個do_
事件,意味著它具有替換Session.execute()
方法通常執行的操作的能力。其預期用途包括分片和結果快取方案,這些方案可能希望在多個資料庫連線上呼叫相同的語句,返回從每個連線合並的結果,或者根本不呼叫語句,而是從快取返回資料。
該鉤子旨在取代在 SQLAlchemy 1.4 之前可以被子類化的Query._execute_and_instances
方法。
引數:
orm_execute_state - 一個ORMExecuteState
的例項,其中包含有關當前執行的所有資訊,以及用於推導其他常用資訊的輔助函式。有關詳細資訊,請參閱該物件。
另請參閱
執行事件 - 關於如何使用SessionEvents.do_orm_execute()
的頂級文件
ORMExecuteState
- 傳遞給SessionEvents.do_orm_execute()
事件的物件,其中包含有關要呼叫的語句的所有資訊。它還提供了一個介面來擴充套件當前語句、選項和引數,以及一個選項,允許在任何時候以程式設計方式呼叫語句。
ORM 查詢事件 - 包括使用SessionEvents.do_orm_execute()
的示例
Dogpile 快取 - 一個示例,演示如何將 Dogpile 快取與 ORM Session
整合,利用SessionEvents.do_orm_execute()
事件鉤子。
水平分片 - 水平分片示例/擴充套件依賴於SessionEvents.do_orm_execute()
事件鉤子,在多個後端上呼叫 SQL 語句並返回合併結果。
1.4 版本中的新功能。
method loaded_as_persistent(session: Session, instance: _O) → None
攔截特定物件的“載入為永續性”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'loaded_as_persistent')
def receive_loaded_as_persistent(session, instance):
"listen for the 'loaded_as_persistent' event"
# ... (event handling logic) ...
此事件在 ORM 載入過程中被呼叫,與InstanceEvents.load()
事件非常相似。然而,這裡的事件可以連結到Session
類或例項,而不是對映器或類層次結構,並且與其他會話生命週期事件平滑整合。在呼叫此事件時,物件保證存在於會話的標識對映中。
注意
此事件在載入器過程中被呼叫,可能在急載入器完成之前,物件的狀態可能不完整。此外,在物件上呼叫行級重新整理操作將使物件進入新的載入器上下文,干擾現有的載入上下文。有關如何使用SessionEvents.restore_load_context
引數的背景,請參閱有關使用InstanceEvents.restore_load_context
的說明,以解決此場景。
引數:
-
session
– 目標Session
-
instance
– 正在操作的 ORM 對映例項。
另請參閱
物件生命週期事件
method pending_to_persistent(session: Session, instance: _O) → None
攔截特定物件的“掛起到持久”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'pending_to_persistent')
def receive_pending_to_persistent(session, instance):
"listen for the 'pending_to_persistent' event"
# ... (event handling logic) ...
此事件在重新整理過程中被呼叫,類似於在SessionEvents.after_flush()
事件中掃描Session.new
集合。然而,在這種情況下,當呼叫事件時,物件已經被移動到持久狀態。
引數:
-
session
– 目標Session
-
instance
– 正在操作的 ORM 對映例項。
另請參閱
物件生命週期事件
method pending_to_transient(session: Session, instance: _O) → None
攔截特定物件的“掛起到瞬態”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'pending_to_transient')
def receive_pending_to_transient(session, instance):
"listen for the 'pending_to_transient' event"
# ... (event handling logic) ...
當未重新整理的掛起物件從會話中驅逐時,會發生這種較少見的轉換;這可能發生在Session.rollback()
方法回滾事務時,或者在使用Session.expunge()
方法時。
引數:
-
session
– 目標Session
-
instance
– 正在操作的 ORM 對映例項。
另請參閱
物件生命週期事件
method persistent_to_deleted(session: Session, instance: _O) → None
攔截特定物件的“持久到已刪除”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'persistent_to_deleted')
def receive_persistent_to_deleted(session, instance):
"listen for the 'persistent_to_deleted' event"
# ... (event handling logic) ...
當持久物件的標識在重新整理中從資料庫中刪除時,將呼叫此事件,但是物件仍然與Session
關聯,直到事務完成。
如果事務被回滾,則物件再次移動到持久狀態,並呼叫SessionEvents.deleted_to_persistent()
事件。如果事務被提交,則物件變為分離狀態,這將觸發SessionEvents.deleted_to_detached()
事件。
請注意,雖然Session.delete()
方法是標記物件為已刪除的主要公共介面,但許多物件由於級聯規則而被刪除,這些規則直到重新整理時才確定。因此,在重新整理進行之前,沒有辦法捕獲每個將被刪除的物件。因此,在重新整理結束時呼叫SessionEvents.persistent_to_deleted()
事件。
另請參閱
物件生命週期事件
method persistent_to_detached(session: Session, instance: _O) → None
攔截特定物件的“持久到分離”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'persistent_to_detached')
def receive_persistent_to_detached(session, instance):
"listen for the 'persistent_to_detached' event"
# ... (event handling logic) ...
當持久物件從會話中驅逐時,將呼叫此事件。導致此事件發生的許多條件,包括:
-
使用
Session.expunge()
或Session.close()
等方法 -
當物件是該會話事務的 INSERT 語句的一部分時,呼叫
Session.rollback()
方法
引數:
-
session
– 目標Session
-
instance
– 正在操作的 ORM 對映例項。 -
deleted
– 布林值。如果為 True,則表示此物件因被標記為已刪除並重新整理而移動到分離狀態。
另請參閱
物件生命週期事件
method persistent_to_transient(session: Session, instance: _O) → None
攔截特定物件的“持久到瞬時”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'persistent_to_transient')
def receive_persistent_to_transient(session, instance):
"listen for the 'persistent_to_transient' event"
# ... (event handling logic) ...
這種較不常見的轉換髮生在已重新整理的掛起物件從會話中被驅逐時;當Session.rollback()
方法回滾事務時,這種情況可能發生。
引數:
-
session
– 目標Session
-
instance
– 正在操作的 ORM 對映例項。
另請參閱
物件生命週期事件
method transient_to_pending(session: Session, instance: _O) → None
攔截特定物件的“瞬態到掛起”轉換。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeSessionClassOrObject, 'transient_to_pending')
def receive_transient_to_pending(session, instance):
"listen for the 'transient_to_pending' event"
# ... (event handling logic) ...
這個事件是SessionEvents.after_attach()
事件的一個特例,僅在這個特定的轉換中呼叫。通常在Session.add()
呼叫期間呼叫。
引數:
-
session
– 目標Session
-
instance
– 正在操作的 ORM 對映例項。
另請參閱
物件生命週期事件
對映器事件
對映器事件鉤子涵蓋了與單個或多個Mapper
物件相關的事情,這些物件是將使用者定義的類對映到Table
物件的中心配置物件。在Mapper
級別發生的事情包括:
-
每個物件的持久化操作 - 最常見的對映器鉤子是工作單元鉤子,如
MapperEvents.before_insert()
、MapperEvents.after_update()
等。這些事件與更粗粒度的會話級事件形成對比,如SessionEvents.before_flush()
,因為它們在每個物件的重新整理過程中發生;雖然物件上的更細粒度活動更直接,但Session
功能的可用性有限。 -
對映器配置事件 - 另一類重要的對映器鉤子是在類被對映時、對映器被最終化時以及當對映器集合被配置為相互引用時發生的事件。這些事件包括
MapperEvents.instrument_class()
、MapperEvents.before_mapper_configured()
和MapperEvents.mapper_configured()
在單個Mapper
級別,以及MapperEvents.before_configured()
和MapperEvents.after_configured()
在集合的Mapper
物件級別。
物件名稱 | 描述 |
---|---|
MapperEvents | 定義特定於對映的事件。 |
class sqlalchemy.orm.MapperEvents
定義特定於對映的事件。
例如:
from sqlalchemy import event
def my_before_insert_listener(mapper, connection, target):
# execute a stored procedure upon INSERT,
# apply the value to the row to be inserted
target.calculated_value = connection.execute(
text("select my_special_function(%d)" % target.special_number)
).scalar()
# associate the listener function with SomeClass,
# to execute during the "before_insert" hook
event.listen(
SomeClass, 'before_insert', my_before_insert_listener)
可用的目標包括:
-
對映的類
-
對映或待對映類的未對映超類(使用
propagate=True
標誌) -
Mapper
物件 -
Mapper
類本身表示監聽所有對映器。
Mapper 事件提供對對映器關鍵部分的鉤子,包括與物件工具化、物件載入和物件持久化相關的部分。特別是,持久化方法 MapperEvents.before_insert()
和 MapperEvents.before_update()
是增強正在持久化的狀態的流行位置 - 但是,這些方法在幾個重要限制下運作。鼓勵使用者評估 SessionEvents.before_flush()
和 SessionEvents.after_flush()
方法,作為在重新整理期間應用額外資料庫狀態的更靈活和使用者友好的鉤子。
當使用 MapperEvents
時,listen()
函式提供了幾個修飾符。
引數:
-
propagate=False
– 當為 True 時,事件監聽器應用於所有繼承對映器和/或繼承類的對映器,以及任何作為此監聽器目標的對映器。 -
raw=False
– 當為 True 時,傳遞給適用的事件監聽器函式的“target”引數將是例項的InstanceState
管理物件,而不是對映的例項本身。 -
retval=False
–當為 True 時,使用者定義的事件函式必須有一個返回值,其目的是要麼控制後續事件的傳播,要麼透過對映器以其他方式修改正在進行的操作。可能的返回值包括:
-
sqlalchemy.orm.interfaces.EXT_CONTINUE
- 繼續正常事件處理。 -
sqlalchemy.orm.interfaces.EXT_STOP
- 取消鏈中所有後續事件處理程式。 -
其他值 - 特定監聽器指定的返回值。
-
成員
after_configured(), after_delete(), after_insert(), after_mapper_constructed(), after_update(), before_configured(), before_delete(), before_insert(), before_mapper_configured(), before_update(), dispatch, instrument_class(), mapper_configured()
類簽名
類 sqlalchemy.orm.MapperEvents
(sqlalchemy.event.Events
)
method after_configured() → None
在一系列對映器被配置後呼叫。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'after_configured')
def receive_after_configured():
"listen for the 'after_configured' event"
# ... (event handling logic) ...
每次呼叫 configure_mappers()
函式完成其工作後,都會呼叫 MapperEvents.after_configured()
事件。通常在首次使用對映時自動呼叫 configure_mappers()
,以及每當新對映器可用並檢測到新的對映器使用時。
將此事件與MapperEvents.mapper_configured()
事件進行對比,該事件在配置操作進行時基於每個對映器呼叫;與該事件不同,當呼叫此事件時,所有交叉配置(例如反向引用)也將對任何待定對映器可用。還與MapperEvents.before_configured()
進行對比,該事件在系列對映器配置之前呼叫。
此事件只能應用於Mapper
類,而不能應用於單個對映或對映類。它僅對所有對映作為一個整體呼叫:
from sqlalchemy.orm import Mapper
@event.listens_for(Mapper, "after_configured")
def go():
# ...
理論上,這個事件在每個應用程式中只呼叫一次,但實際上在任何新對映器受到configure_mappers()
呼叫時都會被呼叫。如果在已經使用現有對映後構造了新對映,則可能會再次呼叫此事件。要確保特定事件僅被呼叫一次且不再呼叫,可以應用once=True
引數(0.9.4 中新增):
from sqlalchemy.orm import mapper
@event.listens_for(mapper, "after_configured", once=True)
def go():
# ...
另請參閱
MapperEvents.before_mapper_configured()
MapperEvents.mapper_configured()
MapperEvents.before_configured()
method after_delete(mapper: Mapper[_O], connection: Connection, target: _O) → None
在發出對應於該例項的 DELETE 語句後接收物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'after_delete')
def receive_after_delete(mapper, connection, target):
"listen for the 'after_delete' event"
# ... (event handling logic) ...
注意
此事件僅適用於會話重新整理操作,並且不適用於在 ORM 啟用的 INSERT、UPDATE 和 DELETE 語句中描述的 ORM DML 操作。要攔截 ORM DML 事件,請使用SessionEvents.do_orm_execute()
。
此事件用於在給定連線上發出額外的 SQL 語句,以及執行與刪除事件相關的應用程式特定的簿記。
該事件通常在之前的步驟中一次發出多個相同類的物件的 DELETE 語句後呼叫。
警告
Mapper 級別的重新整理事件僅允許對僅限於操作的行的本地屬性進行非常有限的操作,同時允許在給定的Connection
上發出任何 SQL。請完全閱讀Mapper 級別的重新整理事件中關於使用這些方法的指南;通常,應優先使用SessionEvents.before_flush()
方法進行一般的重新整理更改。
引數:
-
mapper
– 此事件的目標Mapper
。 -
connection
– 用於發出此例項的 DELETE 語句的Connection
。這為當前事務提供了一個處理該例項特定於目標資料庫的控制代碼。 -
target
– 正在刪除的對映例項。如果事件配置為raw=True
,則這將是與例項關聯的InstanceState
狀態管理物件。
返回:
此事件不支援返回值。
另請參閱
永續性事件
method after_insert(mapper: Mapper[_O], connection: Connection, target: _O) → None
在發出與該例項對應的 INSERT 語句後接收一個物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'after_insert')
def receive_after_insert(mapper, connection, target):
"listen for the 'after_insert' event"
# ... (event handling logic) ...
注意
此事件僅適用於會話重新整理操作,不適用於描述在 ORM-啟用的 INSERT、UPDATE 和 DELETE 語句中的 ORM DML 操作。要攔截 ORM DML 事件,請使用SessionEvents.do_orm_execute()
。
此事件用於修改例項發生 INSERT 後的僅在 Python 中的狀態,以及在給定連線上發出附加的 SQL 語句。
該事件通常在一批相同類的物件的 INSERT 語句一次性發出後被呼叫。在極為罕見的情況下,如果這不是理想的情況,Mapper
物件可以配置為batch=False
,這將導致例項批次被拆分為單個(效能較差)事件->持久化->事件步驟。
警告
僅允許在操作的行上的區域性屬性上執行非常有限的操作,以及在給定的Connection
上允許發出任何 SQL。 請務必充分閱讀有關使用這些方法的指南的 Mapper 級別重新整理事件的說明;一般情況下,應優先考慮SessionEvents.before_flush()
方法進行一般性重新整理更改。
引數:
-
mapper
– 這個事件目標的Mapper
。 -
connection
– 用於為此例項發出 INSERT 語句的Connection
。這提供了一個控制代碼到目標資料庫上當前事務的處理,該事務特定於此例項。 -
target
– 正在持久化的對映例項。如果事件配置為raw=True
,則這將是與例項關聯的InstanceState
狀態管理物件。
返回值:
不支援此事件的返回值。
另請參閱
持久化事件
method after_mapper_constructed(mapper: Mapper[_O], class_: Type[_O]) → None
當Mapper
完全構建完成時,接收一個類和對映器。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'after_mapper_constructed')
def receive_after_mapper_constructed(mapper, class_):
"listen for the 'after_mapper_constructed' event"
# ... (event handling logic) ...
此事件在初始建構函式完成後呼叫Mapper
。這發生在MapperEvents.instrument_class()
事件之後,也發生在Mapper
對其引數進行初始遍歷以生成其MapperProperty
物件集合之後,該集合可透過Mapper.get_property()
方法和Mapper.iterate_properties
屬性訪問。
該事件與MapperEvents.before_mapper_configured()
事件的不同之處在於它在Mapper
的建構函式內呼叫,而不是在registry.configure()
過程中呼叫。目前,這是唯一一個適用於希望在構造此Mapper
時建立其他對映類的處理程式的事件,這些對映類將在下次執行registry.configure()
時成為同一配置步驟的一部分。
新版本 2.0.2 中新增。
另請參閱
物件版本控制 - 一個示例,演示了使用MapperEvents.before_mapper_configured()
事件建立新的對映器以記錄物件的變更審計歷史。
method after_update(mapper: Mapper[_O], connection: Connection, target: _O) → None
在發出與該例項相對應的 UPDATE 語句之後接收物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'after_update')
def receive_after_update(mapper, connection, target):
"listen for the 'after_update' event"
# ... (event handling logic) ...
注意
此事件僅適用於會話重新整理操作,並且不適用於在 ORM 啟用的 INSERT、UPDATE 和 DELETE 語句中描述的 ORM DML 操作。要攔截 ORM DML 事件,請使用SessionEvents.do_orm_execute()
。
此事件用於修改更新後的例項上的僅在 Python 中的狀態,以及在給定連線上發出附加 SQL 語句。
對於所有標記為“髒”的例項都會呼叫此方法,即使它們的基於列的屬性沒有任何淨變化,並且沒有進行 UPDATE 語句。當物件的任何基於列的屬性被呼叫“設定屬性”操作或其任何集合被修改時,物件被標記為髒。如果在更新時,沒有基於列的屬性有任何淨變化,則不會發出 UPDATE 語句。這意味著被髮送到MapperEvents.after_update()
的例項不能保證已發出 UPDATE 語句。
要檢測物件上基於列的屬性是否有淨變化,從而導致 UPDATE 語句,請使用object_session(instance).is_modified(instance, include_collections=False)
。
在前一步驟一次性發出它們的 UPDATE 語句之後,往往為同一類物件的一批物件呼叫事件。在極其罕見的情況下,如果這不是可取的,Mapper
可以配置為batch=False
,這將導致例項批次被分解為單個(效能較差)事件->持久化->事件步驟。
警告
Mapper 級別的重新整理事件僅允許對僅與正在操作的行本地屬性進行非常有限的操作,並允許在給定的Connection
上發出任何 SQL。請完整閱讀Mapper 級重新整理事件的註釋以獲取有關使用這些方法的指南;一般而言,應首選SessionEvents.before_flush()
方法進行一般的重新整理更改。
引數:
-
mapper
– 這個事件目標的Mapper
。 -
connection
– 用於為此例項發出 UPDATE 語句的Connection
。這提供了一個控制代碼到當前事務的目標資料庫,該事務特定於此例項。 -
target
– 被持久化的對映例項。如果事件配置為raw=True
,則這將是與例項關聯的InstanceState
狀態管理物件。
返回:
此事件不支援返回值。
另請參閱
永續性事件
method before_configured() → None
在一系列對映器配置之前呼叫。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'before_configured')
def receive_before_configured():
"listen for the 'before_configured' event"
# ... (event handling logic) ...
每次呼叫configure_mappers()
函式時,都會呼叫MapperEvents.before_configured()
事件,在函式尚未執行任何工作之前。 configure_mappers()
通常在首次使用對映時自動呼叫,以及每次新的對映器可用並檢測到新的對映器使用時呼叫。
此事件僅適用於Mapper
類,而不適用於單個對映或對映類。它僅為所有對映作為一個整體呼叫:
from sqlalchemy.orm import Mapper
@event.listens_for(Mapper, "before_configured")
def go():
...
將此事件與MapperEvents.after_configured()
進行對比,後者在一系列對映器已配置之後呼叫,以及MapperEvents.before_mapper_configured()
和MapperEvents.mapper_configured()
,它們在每個對映器基礎上呼叫。
理論上,此事件在應用程式中每次呼叫一次,但實際上,任何時候新的對映器都會受到configure_mappers()
呼叫的影響。如果在已使用現有對映器之後構造新對映,則可能會再次呼叫此事件。為確保僅呼叫特定事件一次且不再呼叫,可以應用once=True
引數(0.9.4 中的新功能):
from sqlalchemy.orm import mapper
@event.listens_for(mapper, "before_configured", once=True)
def go():
...
另請參閱
MapperEvents.before_mapper_configured()
MapperEvents.mapper_configured()
MapperEvents.after_configured()
method before_delete(mapper: Mapper[_O], connection: Connection, target: _O) → None
在發出與該例項對應的 DELETE 語句之前接收一個物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'before_delete')
def receive_before_delete(mapper, connection, target):
"listen for the 'before_delete' event"
# ... (event handling logic) ...
注意
此事件僅適用於會話重新整理操作,不適用於在 ORM-Enabled INSERT, UPDATE, 和 DELETE statements 中描述的 ORM DML 操作。要攔截 ORM DML 事件,請使用SessionEvents.do_orm_execute()
。
此事件用於在給定連線上發出額外的 SQL 語句,以及執行與刪除事件相關的應用程式特定簿記。
該事件通常在後續步驟中一次性發出同一類物件的批次 DELETE 語句之前為其進行呼叫。
警告
僅允許在僅對操作的行本地屬性上進行非常有限的操作,以及允許在給定的Connection
上發出任何 SQL 語句。請務必充分閱讀Mapper-level Flush Events 中的注意事項,以獲取使用這些方法的指南;通常,應優先使用SessionEvents.before_flush()
方法進行常規的重新整理更改。
引數:
-
mapper
– 此事件的目標Mapper
。 -
connection
– 用於為此例項發出 DELETE 語句的Connection
。這提供了一個控制代碼進入與此例項特定目標資料庫上的當前事務。 -
target
– 正在刪除的對映例項。如果事件配置為raw=True
,則這將是與例項關聯的InstanceState
狀態管理物件。
返回:
此事件不支援返回值。
另請參閱
持久化事件
method before_insert(mapper: Mapper[_O], connection: Connection, target: _O) → None
在發出與該例項對應的 INSERT 語句之前接收物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'before_insert')
def receive_before_insert(mapper, connection, target):
"listen for the 'before_insert' event"
# ... (event handling logic) ...
注意
此事件僅適用於會話重新整理操作,不適用於 ORM 啟用的 INSERT、UPDATE 和 DELETE 語句中描述的 ORM DML 操作。要攔截 ORM DML 事件,請使用SessionEvents.do_orm_execute()
。
此事件用於在發生 INSERT 之前修改例項上的本地、非物件相關屬性,以及在給定連線上發出附加的 SQL 語句。
在稍後的步驟中一次性發出它們的 INSERT 語句之前,通常為同一類物件的一批物件呼叫此事件。在極為罕見的情況下,如果這不是理想的情況,可以使用batch=False
配置Mapper
物件,這將導致例項批次被拆分為單個(效能較差)事件->持久化->事件步驟。
警告
Mapper 級別的重新整理事件僅允許非常有限的操作,僅限於對正在操作的行本地屬性的操作,以及允許在給定的Connection
上發出任何 SQL。請完全閱讀Mapper 級別重新整理事件中的注意事項,以獲取有關使用這些方法的指南;通常,應優先使用SessionEvents.before_flush()
方法進行一般的重新整理更改。
引數:
-
mapper
– 此事件的目標Mapper
。 -
connection
– 用於為此例項發出 INSERT 語句的Connection
。這提供了一個在目標資料庫上當前事務中使用的控制代碼,該事務特定於此例項。 -
target
– 正在持久化的對映例項。如果事件配置為raw=True
,則這將改為與例項關聯的InstanceState
狀態管理物件。
返回:
此事件不支援返回值。
另請參閱
永續性事件
method before_mapper_configured(mapper: Mapper[_O], class_: Type[_O]) → None
在特定對映器配置之前呼叫。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'before_mapper_configured')
def receive_before_mapper_configured(mapper, class_):
"listen for the 'before_mapper_configured' event"
# ... (event handling logic) ...
此事件旨在允許在配置步驟中跳過特定對映器,方法是返回 interfaces.EXT_SKIP
符號,該符號表示向 configure_mappers()
呼叫指示此特定對映器(或如果使用 propagate=True
則是對映器層次結構)應在當前配置執行中被跳過。當跳過一個或多個對映器時,將保持“新對映器”標誌設定,這意味著當使用對映器時,將繼續呼叫 configure_mappers()
函式,以繼續嘗試配置所有可用的對映器。
與其他配置級事件 MapperEvents.before_configured()
、MapperEvents.after_configured()
和 MapperEvents.mapper_configured()
相比,當使用 retval=True
引數註冊時,:meth;.MapperEvents.before_mapper_configured
事件在註冊時提供了有意義的返回值。
版本 1.3 中的新功能。
例如:
from sqlalchemy.orm import EXT_SKIP
Base = declarative_base()
DontConfigureBase = declarative_base()
@event.listens_for(
DontConfigureBase,
"before_mapper_configured", retval=True, propagate=True)
def dont_configure(mapper, cls):
return EXT_SKIP
另請參閱
MapperEvents.before_configured()
MapperEvents.after_configured()
MapperEvents.mapper_configured()
method before_update(mapper: Mapper[_O], connection: Connection, target: _O) → None
在發出相應於該例項的 UPDATE 語句之前接收物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'before_update')
def receive_before_update(mapper, connection, target):
"listen for the 'before_update' event"
# ... (event handling logic) ...
注
此事件僅適用於會話重新整理操作,不適用於 ORM 啟用的 INSERT、UPDATE 和 DELETE 語句中描述的 ORM DML 操作。要攔截 ORM DML 事件,請使用SessionEvents.do_orm_execute()
。
此事件用於在 UPDATE 發生之前修改例項上的本地、非物件相關屬性,以及在給定連線上發出額外的 SQL 語句。
此方法適用於所有被標記為“髒”的例項,即使它們的基於列的屬性沒有淨變化。當物件的任何基於列的屬性被呼叫“設定屬性”操作或其集合被修改時,物件被標記為髒。如果在更新時,沒有基於列的屬性有任何淨變化,那麼不會發出 UPDATE 語句。這意味著將例項傳送到MapperEvents.before_update()
並不保證會發出 UPDATE 語句,儘管您可以透過修改屬性以使值存在淨變化來影響結果。
要檢測物件的基於列的屬性是否有淨變化,並因此生成 UPDATE 語句,請使用object_session(instance).is_modified(instance, include_collections=False)
。
在稍後的步驟中,通常在一批相同類的物件之前呼叫此事件,然後一次發出它們的 UPDATE 語句。在極為罕見的情況下,如果這不可取,可以配置Mapper
為batch=False
,這將導致例項批次被拆分為單個(效能較差)事件->持久化->事件步驟。
警告
Mapper 級別的重新整理事件僅允許非常有限的操作,僅限於操作的行本地屬性,以及允許在給定的Connection
上發出任何 SQL。請完全閱讀Mapper 級別重新整理事件中的注意事項,以獲取有關使用這些方法的指導;通常,應優先使用SessionEvents.before_flush()
方法進行一般的重新整理更改。
引數:
-
mapper
– 此事件目標的Mapper
。 -
connection
– 用於為此例項發出 UPDATE 語句的Connection
。這提供了一個控制代碼進入當前資料庫的事務,特定於此例項。 -
target
– 正在持久化的對映例項。如果事件配置為raw=True
,則這將是與例項關聯的InstanceState
狀態管理物件。
返回值:
此事件不支援返回值。
另請參見
永續性事件
attribute dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.MapperEventsDispatch object>
參考回到 _Dispatch 類。
雙向反對 _Dispatch._events
method instrument_class(mapper: Mapper[_O], class_: Type[_O]) → None
當對映器首次構造時接收類,然後應用到對映類之前的儀器。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'instrument_class')
def receive_instrument_class(mapper, class_):
"listen for the 'instrument_class' event"
# ... (event handling logic) ...
此事件是對映器構造的最早階段。大多數對映器的屬性尚未初始化。要在初始對映器構造中接收事件,在其中可以使用基本狀態的情況下,例如 Mapper.attrs
集合,可能更好地選擇 MapperEvents.after_mapper_constructed()
事件。
此偵聽器可以應用於整個 Mapper
類,也可以應用於任何未對映的類,該類用作將要對映的類的基類(使用 propagate=True
標誌):
Base = declarative_base()
@event.listens_for(Base, "instrument_class", propagate=True)
def on_new_class(mapper, cls_):
" ... "
引數:
-
mapper
– 此事件目標的Mapper
。 -
class_
– 對映的類。
另請參見
MapperEvents.after_mapper_constructed()
method mapper_configured(mapper: Mapper[_O], class_: Type[_O]) → None
當特定對映器在 configure_mappers()
呼叫範圍內完成其自身配置時呼叫。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'mapper_configured')
def receive_mapper_configured(mapper, class_):
"listen for the 'mapper_configured' event"
# ... (event handling logic) ...
當 configure_mappers()
函式透過當前尚未配置的對映器列表進行時,對遇到的每個對映器呼叫 MapperEvents.mapper_configured()
事件。通常在首次使用對映時自動呼叫 configure_mappers()
,以及每次有新對映器可用並檢測到新對映器使用時。
當呼叫事件時,對映器應處於最終狀態,但不包括可能從其他對映器呼叫的反向引用;它們可能仍在配置操作中掛起。透過relationship.back_populates
引數配置的雙向關係將完全可用,因為這種關係方式不依賴於其他可能尚未配置的對映器來知道它們的存在。
對於一個保證所有對映都準備就緒,包括僅在其他對映上定義的反向引用的事件,請使用MapperEvents.after_configured()
事件;此事件僅在所有已知對映完全配置後才呼叫。
與MapperEvents.before_configured()
或MapperEvents.after_configured()
不同,MapperEvents.mapper_configured()
事件為每個對映/類單獨呼叫,並將對映器傳遞給事件本身。對於特定對映器,該事件僅呼叫一次。因此,該事件對於在特定對映器基礎上僅呼叫一次的配置步驟非常有用,這些步驟不要求“反向引用”配置必須已準備就緒。
引數:
-
mapper
– 這個事件的目標是Mapper
。 -
class_
– 對映的類。
另請參閱
MapperEvents.before_configured()
MapperEvents.after_configured()
MapperEvents.before_mapper_configured()
例項事件
例項事件專注於 ORM 對映例項的構建,包括當它們作為瞬態物件例項化時,當它們從資料庫載入併成為持久物件時,以及當資料庫重新整理或過期操作發生在物件上時。
物件名稱 | 描述 |
---|---|
InstanceEvents | 定義特定於物件生命週期的事件。 |
class sqlalchemy.orm.InstanceEvents
定義特定於物件生命週期的事件。
例如:
from sqlalchemy import event
def my_load_listener(target, context):
print("on load!")
event.listen(SomeClass, 'load', my_load_listener)
可用的目標包括:
-
已對映的類
-
已對映或將要對映的類的未對映超類(使用
propagate=True
標誌) -
Mapper
物件 -
Mapper
類本身指示偵聽所有對映器。
例項事件與對映器事件密切相關,但更具體於例項及其儀器化,而不是其持久化系統。
使用InstanceEvents
時,listen()
函式提供了幾個修飾符。
引數:
-
propagate=False
– 當為 True 時,事件監聽器應該應用於所有繼承類,以及作為此監聽器目標的類。 -
raw=False
– 當為 True 時,適用的事件監聽器函式傳遞給“target”引數將是例項的InstanceState
管理物件,而不是對映例項本身。 -
restore_load_context=False
–適用於
InstanceEvents.load()
和InstanceEvents.refresh()
事件。在事件鉤子完成後恢復物件的載入器上下文,以便持續的急載入操作繼續適當地針對物件。如果在這些事件之一內部將物件移動到新的載入器上下文中並且未設定此標誌,則會發出警告。版本 1.3.14 中的新內容。
成員
dispatch, expire(), first_init(), init(), init_failure(), load(), pickle(), refresh(), refresh_flush(), unpickle()
類簽名
類sqlalchemy.orm.InstanceEvents
(sqlalchemy.event.Events
)
attribute dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.InstanceEventsDispatch object>
回溯到 _Dispatch 類。
雙向對 _Dispatch._events
method expire(target: _O, attrs: Iterable[str] | None) → None
在其屬性或某些子集被過期後接收物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'expire')
def receive_expire(target, attrs):
"listen for the 'expire' event"
# ... (event handling logic) ...
‘keys’是屬性名稱列表。如果為 None,則整個狀態已過期。
引數:
-
target
– 對映例項。如果事件配置為raw=True
,則此處將替代與例項關聯的InstanceState
狀態管理物件。 -
attrs
– 被過期的屬性名稱序列,如果所有屬性均已過期則為 None。
method first_init(manager: ClassManager[_O], cls: Type[_O]) → None
當特定對映的第一個例項被呼叫時呼叫。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'first_init')
def receive_first_init(manager, cls):
"listen for the 'first_init' event"
# ... (event handling logic) ...
當為該特定類第一次呼叫__init__
方法時呼叫此事件。該事件在__init__
實際執行之前以及在呼叫InstanceEvents.init()
事件之前呼叫。
method init(target: _O, args: Any, kwargs: Any) → None
當其建構函式被呼叫時接收一個例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'init')
def receive_init(target, args, kwargs):
"listen for the 'init' event"
# ... (event handling logic) ...
此方法僅在物件的使用者空間構造期間呼叫,與物件的建構函式(例如其__init__
方法)一起。當物件從資料庫載入時不會呼叫它;請參閱InstanceEvents.load()
事件以攔截資料庫載入。
在實際呼叫物件的__init__
建構函式之前呼叫該事件。kwargs
字典可以就地修改,以影響傳遞給__init__
的內容。
引數:
-
target
– 對映的例項。如果事件配置為raw=True
,則這將是與該例項關聯的InstanceState
狀態管理物件。 -
args
– 傳遞給__init__
方法的位置引數。這將作為元組傳遞,目前不可變。 -
kwargs
– 傳遞給__init__
方法的關鍵字引數。此結構可以就地更改。
另請參閱
InstanceEvents.init_failure()
InstanceEvents.load()
method init_failure(target: _O, args: Any, kwargs: Any) → None
當其建構函式被呼叫並引發異常時接收一個例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'init_failure')
def receive_init_failure(target, args, kwargs):
"listen for the 'init_failure' event"
# ... (event handling logic) ...
此方法僅在物件的使用者空間構造期間呼叫,與物件的建構函式(例如其__init__
方法)一起。當物件從資料庫載入時不會呼叫它。
在捕獲到__init__
方法引發的異常後呼叫該事件。呼叫事件後,原始異常將重新引發,以便物件的構造仍然引發異常。應在sys.exc_info()
中提供實際異常和堆疊跟蹤引發的異常。
引數:
-
target
– 對映的例項。如果事件配置為raw=True
,則這將是與該例項關聯的InstanceState
狀態管理物件。 -
args
– 傳遞給__init__
方法的位置引數。 -
kwargs
– 傳遞給__init__
方法的關鍵字引數。
另請參閱
InstanceEvents.init()
InstanceEvents.load()
method load(target: _O, context: QueryContext) → None
在透過 __new__
建立物件例項並進行初始屬性填充之後接收物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'load')
def receive_load(target, context):
"listen for the 'load' event"
# ... (event handling logic) ...
這通常發生在基於傳入結果行建立例項時,並且僅針對該例項的生命週期呼叫一次。
警告
在結果行載入期間,當處理此例項的第一行接收到時會呼叫此事件。當使用帶有集合定向屬性的急切載入時,用於載入後續集合項的其他行尚未發生 / 處理。這既會導致集合不會完全載入,也會導致如果在此事件處理程式內發生了導致物件發出另一個資料庫載入操作的操作,則物件的“載入上下文”可能會發生變化,並干擾正在進行的現有急切載入程式。
導致事件處理程式內的“載入上下文”發生變化的原因示例包括但不限於:
-
訪問未包含在行中的延遲屬性將觸發“取消延遲”操作並重新整理物件。
-
訪問未包含在行中的聯接繼承子類的屬性將觸發重新整理操作。
從 SQLAlchemy 1.3.14 開始,當發生這種情況時會發出警告。InstanceEvents.restore_load_context
選項可用於事件上以防止此警告;這將確保在呼叫事件後保持物件的現有載入上下文:
@event.listens_for(
SomeClass, "load", restore_load_context=True)
def on_load(instance, context):
instance.some_unloaded_attribute
1.3.14 版更改:增加了 InstanceEvents.restore_load_context
和 SessionEvents.restore_load_context
標誌,適用於“載入”事件,將確保在事件掛鉤完成時恢復物件的載入上下文;如果沒有設定此標誌,則會發出警告,指示物件的載入上下文發生了變化。
InstanceEvents.load()
事件也以類方法裝飾器格式可用,稱為 reconstructor()
。
引數:
-
target
– 對映的例項。如果事件配置了raw=True
,則會變成與例項關聯的InstanceState
狀態管理物件。 -
context
– 與當前進行中的Query
對應的QueryContext
。如果載入不對應於Query
,例如在Session.merge()
期間,此引數可能為None
。
另請參閱
維護跨載入的非對映狀態
InstanceEvents.init()
InstanceEvents.refresh()
SessionEvents.loaded_as_persistent()
method pickle(target: _O, state_dict: _InstanceDict) → None
在其關聯狀態被 pickled 時接收物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'pickle')
def receive_pickle(target, state_dict):
"listen for the 'pickle' event"
# ... (event handling logic) ...
引數:
-
target
– 對映例項。如果事件配置為raw=True
,則這將是與例項關聯的InstanceState
狀態管理物件。 -
state_dict
– 由__getstate__
返回的字典,包含要被 pickled 的狀態。
method refresh(target: _O, context: QueryContext, attrs: Iterable[str] | None) → None
在從查詢中重新整理一個或多個屬性後接收物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'refresh')
def receive_refresh(target, context, attrs):
"listen for the 'refresh' event"
# ... (event handling logic) ...
與InstanceEvents.load()
方法形成對比,當物件首次從查詢中載入時會呼叫該方法。
注意
在載入器程序中在急切載入器可能已完成之前呼叫此事件,並且物件的狀態可能不完整。此外,在物件上呼叫行級重新整理操作將使物件進入新的載入器上下文,干擾現有的載入上下文。有關如何利用InstanceEvents.restore_load_context
引數解決此場景的背景,請參閱有關InstanceEvents.load()
的註釋。
引數:
-
target
– 對映例項。如果事件配置為raw=True
,則這將是與例項關聯的InstanceState
狀態管理物件。 -
context
– 與當前進行中的Query
對應的QueryContext
。 -
attrs
– 已填充的屬性名稱序列,如果所有列對映的非延遲屬性都已填充,則為 None。
另請參閱
在載入過程中保持非對映狀態
InstanceEvents.load()
method refresh_flush(target: _O, flush_context: UOWTransaction, attrs: Iterable[str] | None) → None
在物件的狀態持久化過程中,當一個或多個包含列級預設值或 onupdate 處理程式的屬性被重新整理後,會收到一個物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'refresh_flush')
def receive_refresh_flush(target, flush_context, attrs):
"listen for the 'refresh_flush' event"
# ... (event handling logic) ...
此事件與InstanceEvents.refresh()
相同,只是在工作單元重新整理過程中呼叫,並且僅包括具有列級預設值或 onupdate 處理程式的非主鍵列,包括 Python 可呼叫物件以及透過 RETURNING 子句獲取的伺服器端預設值和觸發器。
注意
雖然InstanceEvents.refresh_flush()
事件是為 INSERT 和 UPDATE 的物件觸發的,但該事件主要針對 UPDATE 過程;這主要是一個內部工件,INSERT 操作也可以觸發此事件,並注意INSERT 行的主鍵列明確地在此事件中被省略。為了攔截物件的新 INSERT 狀態,SessionEvents.pending_to_persistent()
和MapperEvents.after_insert()
是更好的選擇。
引數:
-
target
– 對映例項。如果事件配置為raw=True
,那麼這將是與例項關聯的InstanceState
狀態管理物件。 -
flush_context
– 處理重新整理細節的內部UOWTransaction
物件。 -
attrs
– 被填充的屬性名稱序列。
另請參閱
在載入過程中保持非對映狀態
獲取伺服器生成的預設值
列的 INSERT/UPDATE 預設值
method unpickle(target: _O, state_dict: _InstanceDict) → None
在關聯狀態被反 pickle 後,收到一個物件例項。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass, 'unpickle')
def receive_unpickle(target, state_dict):
"listen for the 'unpickle' event"
# ... (event handling logic) ...
引數:
-
target
– 對映例項。如果事件配置為raw=True
,那麼這將是與例項關聯的InstanceState
狀態管理物件。 -
state_dict
– 傳送給__setstate__
的字典,包含被 pickle 的狀態字典。
屬性事件
屬性事件在 ORM 對映物件的各個屬性發生事情時觸發。這些事件構成了諸如自定義驗證函式和反向引用處理程式等功能的基礎。
另請參閱
更改屬性行為
物件名稱 | 描述 |
---|---|
AttributeEvents | 為物件屬性定義事件。 |
class sqlalchemy.orm.AttributeEvents
為物件屬性定義事件。
這些通常在目標類的類繫結描述符上定義。
例如,要註冊一個將接收AttributeEvents.append()
事件的監聽器:
from sqlalchemy import event
@event.listens_for(MyClass.collection, 'append', propagate=True)
def my_append_listener(target, value, initiator):
print("received append event for target: %s" % target)
當AttributeEvents.retval
標誌傳遞給listen()
或listens_for()
時,監聽器可以選擇返回可能修改的值的版本,如下所示,使用AttributeEvents.set()
事件進行說明:
def validate_phone(target, value, oldvalue, initiator):
"Strip non-numeric characters from a phone number"
return re.sub(r'\D', '', value)
# setup listener on UserContact.phone attribute, instructing
# it to use the return value
listen(UserContact.phone, 'set', validate_phone, retval=True)
類似上述的驗證函式也可以引發異常,如ValueError
以停止操作。
當將監聽器應用於具有對映子類的對映類時,AttributeEvents.propagate
標誌也很重要,例如在使用對映器繼承模式時:
@event.listens_for(MySuperClass.attr, 'set', propagate=True)
def receive_set(target, value, initiator):
print("value set: %s" % target)
listen()
和 listens_for()
函式可用的所有修飾符如下。
引數:
-
active_history=False
– 當為 True 時,表示“set”事件希望無條件接收被替換的“舊”值,即使這需要觸發資料庫載入。請注意,active_history
也可以透過column_property()
和relationship()
直接設定。 -
propagate=False
– 當為 True 時,監聽器函式將不僅為給定的類屬性建立,還將為該類的所有當前子類以及該類的所有未來子類上具有相同名稱的屬性建立一個額外的監聽器,該監聽器監聽儀器事件。 -
raw=False
– 當為 True 時,事件的“target”引數將是InstanceState
管理物件,而不是對映例項本身。 -
retval=False
– 當為 True 時,使用者定義的事件監聽必須從函式返回“value”引數。這使得監聽函式有機會改變最終用於“set”或“append”事件的值。
成員
append(), append_wo_mutation(), bulk_replace(), dispatch, dispose_collection(), init_collection(), init_scalar(), modified(), remove(), set()
類簽名
類sqlalchemy.orm.AttributeEvents
(sqlalchemy.event.Events
)
method append(target: _O, value: _T, initiator: Event, *, key: EventConstants = EventConstants.NO_KEY) → _T | None
接收集合追加事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'append')
def receive_append(target, value, initiator):
"listen for the 'append' event"
# ... (event handling logic) ...
每當元素被追加到集合中時,都會呼叫追加事件。這適用於單個元素追加以及“批次替換”操作。
引數:
-
target
– 接收事件的物件例項。如果監聽器註冊為raw=True
,則這將是InstanceState
物件。 -
value
– 被追加的值。如果此監聽器註冊為retval=True
,則監聽函式必須返回此值,或替換它的新值。 -
initiator
– 一個代表事件啟動的Event
例項。可能會被 backref 處理程式修改其原始值,以控制鏈式事件傳播,同時也可以被檢查以獲取有關事件源的資訊。 -
key
–當使用
AttributeEvents.include_key
引數設定為 True 來建立事件時,這將是操作中使用的鍵,例如collection[some_key_or_index] = value
。如果未使用AttributeEvents.include_key
設定事件,則根本不會傳遞該引數;這是為了允許與不包括key
引數的現���事件處理程式向後相容。2.0 版中的新內容。
返回值:
如果事件註冊時使用retval=True
,應返回給定值或新的有效值。
另請參閱
AttributeEvents
- 關於監聽器選項的背景,如傳播到子類。
AttributeEvents.bulk_replace()
method append_wo_mutation(target: _O, value: _T, initiator: Event, *, key: EventConstants = EventConstants.NO_KEY) → None
接收一個集合追加事件,其中集合實際上未發生變化。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'append_wo_mutation')
def receive_append_wo_mutation(target, value, initiator):
"listen for the 'append_wo_mutation' event"
# ... (event handling logic) ...
此事件與AttributeEvents.append()
不同,因為它是為了去重集合(如集合和字典)而觸發的,當物件已經存在於目標集合中時。該事件沒有返回值,給定物件的標識不能更改。
當集合已透過反向引用事件發生變異時,此事件用於級聯物件到Session
。
引數:
-
target
– 接收事件的物件例項。如果偵聽器註冊為raw=True
,這將是InstanceState
物件。 -
value
– 如果物件尚未存在於集合中,則將要附加的值。 -
initiator
– 代表事件啟動的Event
例項。可以透過反向引用處理程式修改其原始值,以控制鏈式事件傳播,並且可以檢查有關事件源的資訊。 -
key
–當使用
AttributeEvents.include_key
引數設定為 True 來建立事件時,這將是操作中使用的鍵,例如collection[some_key_or_index] = value
。如果沒有使用AttributeEvents.include_key
來設定事件,則根本不會將引數傳遞給事件;這是為了允許與不包括key
引數的現有事件處理程式保持向後相容。版本 2.0 中的新內容。
返回值:
沒有為此事件定義返回值。
版本 1.4.15 中的新內容。
method bulk_replace(target: _O, values: Iterable[_T], initiator: Event, *, keys: Iterable[EventConstants] | None = None) → None
接收一個集合‘批次替換’事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'bulk_replace')
def receive_bulk_replace(target, values, initiator):
"listen for the 'bulk_replace' event"
# ... (event handling logic) ...
當值作為批次集合設定操作的一部分傳入時,將呼叫此事件,可以在值被視為 ORM 物件之前就地修改。這是一個“早期掛鉤”,在批次替換例程嘗試協調哪些物件已經存在於集合中,哪些物件被淨替換操作移除之前執行。
通常情況下,這個方法會與AttributeEvents.append()
事件一起使用。當同時使用這兩個事件時,請注意,批次替換操作將為所有新專案呼叫AttributeEvents.append()
事件,即使在為整個集合呼叫AttributeEvents.bulk_replace()
之後。為了確定AttributeEvents.append()
事件是否是批次替換的一部分,請使用符號attributes.OP_BULK_REPLACE
來測試傳入的 initiator:
from sqlalchemy.orm.attributes import OP_BULK_REPLACE
@event.listens_for(SomeObject.collection, "bulk_replace")
def process_collection(target, values, initiator):
values[:] = [_make_value(value) for value in values]
@event.listens_for(SomeObject.collection, "append", retval=True)
def process_collection(target, value, initiator):
# make sure bulk_replace didn't already do it
if initiator is None or initiator.op is not OP_BULK_REPLACE:
return _make_value(value)
else:
return value
版本 1.2 中的新功能。
引數:
-
target
– 接收事件的物件例項。如果監聽器以raw=True
註冊,這將是InstanceState
物件。 -
value
– 被設定的值的序列(例如列表)。處理程式可以直接修改此列表。 -
initiator
– 代表事件啟動的Event
例項。 -
keys
–當使用
AttributeEvents.include_key
引數設定為 True 來建立事件時,這將是操作中使用的鍵的序列,通常僅用於字典更新。如果未使用AttributeEvents.include_key
設定事件,引數根本不會傳遞給事件;這是為了允許與不包括key
引數的現有事件處理程式保持向後相容。版本 2.0 中的新功能。
另請參見
AttributeEvents
- 關於監聽器選項的背景,例如傳播到子類。
attribute dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.AttributeEventsDispatch object>
參考回到 _Dispatch 類。
雙向對 _Dispatch._events
method dispose_collection(target: _O, collection: Collection[Any], collection_adapter: CollectionAdapter) → None
接收“集合處理”事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'dispose_collection')
def receive_dispose_collection(target, collection, collection_adapter):
"listen for the 'dispose_collection' event"
# ... (event handling logic) ...
當集合被替換時,此事件將為基於集合的屬性觸發,即:
u1.addresses.append(a1)
u1.addresses = [a2, a3] # <- old collection is disposed
舊集合接收到的將包含其先前的內容。
版本 1.2 中的更改:傳遞給AttributeEvents.dispose_collection()
的集合現在在處理之前會保持其內容;以前,集合將為空。
另請參見
AttributeEvents
- 關於監聽器選項的背景,例如傳播到子類。
method init_collection(target: _O, collection: Type[Collection[Any]], collection_adapter: CollectionAdapter) → None
接收“集合初始化”事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'init_collection')
def receive_init_collection(target, collection, collection_adapter):
"listen for the 'init_collection' event"
# ... (event handling logic) ...
當為空屬性首次生成初始的“空集合”時以及當集合被新集合替換時,例如透過 set 事件,將觸發此事件。
例如,給定User.addresses
是基於關係的集合,此處觸發事件:
u1 = User()
u1.addresses.append(a1) # <- new collection
並且在替換操作期間也是如此:
u1.addresses = [a2, a3] # <- new collection
引數:
-
target
– 接收事件的物件例項。如果監聽器註冊為raw=True
,則這將是InstanceState
物件。 -
collection
– 新的集合。這將始終從relationship.collection_class
中指定的內容生成,並且始終為空。 -
collection_adapter
– 將調解對集合的內部訪問的CollectionAdapter
。
另請參閱
AttributeEvents
- 關於監聽器選項的背景,例如傳播到子類。
AttributeEvents.init_scalar()
- 此事件的“標量”版本。
method init_scalar(target: _O, value: _T, dict_: Dict[Any, Any]) → None
接收一個標量“init”事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'init_scalar')
def receive_init_scalar(target, value, dict_):
"listen for the 'init_scalar' event"
# ... (event handling logic) ...
當訪問未初始化的、未持久化的標量屬性時,會呼叫此事件,例如讀取:
x = my_object.some_attribute
當此事件發生在未初始化的屬性上時,ORM 的預設行為是返回值None
;請注意,這與 Python 的通常行為不同,Python 通常會引發AttributeError
。此處的事件可用於自定義實際返回的值,假設事件偵聽器將映象配置在 Core Column
物件上的預設生成器。
由於Column
上的預設生成器可能也會產生一個變化的值,例如時間戳,所以AttributeEvents.init_scalar()
事件處理程式也可以用於設定新返回的值,以便 Core 級別的預設生成函式僅在訪問非持久化物件上的屬性時觸發一次,但是在這一刻。通常,當訪問未初始化的屬性時,不會對物件的狀態進行任何更改(較舊的 SQLAlchemy 版本實際上會更改物件的狀態)。
如果列上的預設生成器返回特定常量,則可能會使用處理程式如下:
SOME_CONSTANT = 3.1415926
class MyClass(Base):
# ...
some_attribute = Column(Numeric, default=SOME_CONSTANT)
@event.listens_for(
MyClass.some_attribute, "init_scalar",
retval=True, propagate=True)
def _init_some_attribute(target, dict_, value):
dict_['some_attribute'] = SOME_CONSTANT
return SOME_CONSTANT
在上面的示例中,我們將屬性MyClass.some_attribute
初始化為SOME_CONSTANT
的值。以上程式碼包括以下功能:
-
透過在給定的
dict_
中設定值SOME_CONSTANT
,我們指示該值將被持久化到資料庫中。這將取代在Column
的預設生成器中使用SOME_CONSTANT
。在屬性儀器化中給出的active_column_defaults.py
示例說明了使用相同方法進行更改預設值的方法,例如時間戳生成器。在這個特定的例子中,這樣做並不是嚴格必要的,因為SOME_CONSTANT
無論如何都會成為 INSERT 語句的一部分。 -
透過建立
retval=True
標誌,我們從函式返回的值將由屬性獲取器返回。沒有此標誌,事件被視為被動觀察者,我們函式的返回值將被忽略。 -
如果對映類包括繼承的子類,則
propagate=True
標誌是重要的,這些子類也會使用此事件偵聽器。沒有此標誌,繼承的子類將不使用我們的事件處理程式。
在上述示例中,當我們將值應用於給定的dict_
時,不會呼叫屬性設定事件AttributeEvents.set()
以及由validates
提供的相關驗證功能。要使這些事件響應我們新生成的值而呼叫,請將該值應用於給定物件作為普通屬性設定操作:
SOME_CONSTANT = 3.1415926
@event.listens_for(
MyClass.some_attribute, "init_scalar",
retval=True, propagate=True)
def _init_some_attribute(target, dict_, value):
# will also fire off attribute set events
target.some_attribute = SOME_CONSTANT
return SOME_CONSTANT
當設定了多個偵聽器時,值的生成會從一個偵聽器“鏈式”傳遞到下一個偵聽器,透過將由前一個指定了retval=True
的偵聽器返回的值作為下一個偵聽器的value
引數傳遞。
引數:
-
target
– 接收事件的物件例項。如果偵聽器使用raw=True
註冊,這將是InstanceState
物件。 -
value
– 在呼叫此事件偵聽器之前要返回的值。此值最初為值None
,但如果存在多個偵聽器,則將是前一個事件處理程式函式的返回值。 -
dict_
– 此對映物件的屬性字典。這通常是物件的__dict__
,但在所有情況下都表示屬性系統用於訪問此屬性的實際值的目標。將值放入此字典中的效果是該值將在工作單元生成的 INSERT 語句中使用。
另請參見
AttributeEvents.init_collection()
- 此事件的集合版本
AttributeEvents
- 關於偵聽器選項的背景,例如傳播到子類。
屬性儀表化 - 檢視 active_column_defaults.py
示例。
method modified(target: _O, initiator: Event) → None
接收一個“修改”事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'modified')
def receive_modified(target, initiator):
"listen for the 'modified' event"
# ... (event handling logic) ...
當使用 flag_modified()
函式觸發屬性上的修改事件時,會觸發此事件,而不設定任何特定值。
新版本 1.2 中的內容。
引數:
-
target
– 接收事件的物件例項。如果偵聽器註冊為raw=True
,則這將是InstanceState
物件。 -
initiator
– 表示事件啟動的Event
的例項。
另請參閱
AttributeEvents
- 有關偵聽器選項的背景,如傳播到子類。
method remove(target: _O, value: _T, initiator: Event, *, key: EventConstants = EventConstants.NO_KEY) → None
接收一個集合移除事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'remove')
def receive_remove(target, value, initiator):
"listen for the 'remove' event"
# ... (event handling logic) ...
引數:
-
target
– 接收事件的物件例項。如果偵聽器註冊為raw=True
,則這將是InstanceState
物件。 -
value
– 被移除的值。 -
initiator
– 表示事件啟動的Event
的例項。可能會被 backref 處理程式修改其原始值,以控制鏈式事件傳播。 -
key
–當使用
AttributeEvents.include_key
引數設定為 True 來建立事件時,這將是操作中使用的鍵,例如del collection[some_key_or_index]
。如果未使用AttributeEvents.include_key
來設定事件,則根本不會傳遞該引數給事件;這是為了與不包括key
引數的現有事件處理程式的向後相容性。新版本 2.0 中的內容。
返回:
此事件未定義返回值。
另請參閱
AttributeEvents
- 有關偵聽器選項的背景,如傳播到子類。
method set(target: _O, value: _T, oldvalue: _T, initiator: Event) → None
接收一個標量設定事件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeClass.some_attribute, 'set')
def receive_set(target, value, oldvalue, initiator):
"listen for the 'set' event"
# ... (event handling logic) ...
引數:
-
target
– 接收事件的物件例項。如果偵聽器註冊為raw=True
,則這將是InstanceState
物件。 -
value
– 被設定的值。如果此偵聽器註冊為retval=True
,則偵聽器函式必須返回此值,或者替換它的新值。 -
oldvalue
– 被替換的先前值。這也可以是符號NEVER_SET
或NO_VALUE
。如果偵聽器註冊為active_history=True
,則如果現有值當前未載入或過期,則將從資料庫載入屬性的先前值。 -
initiator
– 代表事件啟動的Event
例項。可能會被 backref 處理程式修改其原始值,以控制鏈式事件傳播。
返回值:
如果事件是以retval=True
註冊的,則應返回給定值或新的有效值。
另請參閱
AttributeEvents
- 關於偵聽器選項的背景,如傳播到子類。
查詢事件
物件名稱 | 描述 |
---|---|
QueryEvents | 在構建Query 物件時表示事件。 |
class sqlalchemy.orm.QueryEvents
在構建Query
物件時表示事件。
傳統特性
QueryEvents
事件方法在 SQLAlchemy 2.0 中已過時,僅適用於直接使用Query
物件。它們不適用於 2.0 風格語句。要攔截和修改 2.0 風格 ORM 使用的事件,請使用SessionEvents.do_orm_execute()
鉤子。
QueryEvents
鉤子現在已被SessionEvents.do_orm_execute()
事件鉤取代。
成員
before_compile(), before_compile_delete(), before_compile_update(), dispatch
類簽名
類sqlalchemy.orm.QueryEvents
(sqlalchemy.event.Events
)
method before_compile(query: Query) → None
在將其組成為核心Select
物件之前接收Query
物件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeQuery, 'before_compile')
def receive_before_compile(query):
"listen for the 'before_compile' event"
# ... (event handling logic) ...
自 1.4 版本起已棄用:QueryEvents.before_compile()
事件被更強大的SessionEvents.do_orm_execute()
鉤子取代。在 1.4 版本中,QueryEvents.before_compile()
事件不再用於 ORM 級別的屬性載入,例如延遲載入或過期屬性以及關聯載入器的載入。請參閱 ORM 查詢事件中的新示例,該示例說明了攔截和修改 ORM 查詢以新增任意篩選條件的常見目的的新方法。
此事件旨在允許對給定的查詢進行更改:
@event.listens_for(Query, "before_compile", retval=True)
def no_deleted(query):
for desc in query.column_descriptions:
if desc['type'] is User:
entity = desc['entity']
query = query.filter(entity.deleted == False)
return query
通常應該使用retval=True
引數監聽事件,以便修改後的查詢可以返回。
預設情況下,QueryEvents.before_compile()
事件將禁止“baked”查詢快取查詢,如果事件鉤子返回一個新的Query
物件。這影響到對烘焙查詢擴充套件的直接使用以及它在延遲載入器和關係的貪婪載入器中的操作。為了重新建立快取查詢,請應用新增了bake_ok
標誌的事件:
@event.listens_for(
Query, "before_compile", retval=True, bake_ok=True)
def my_event(query):
for desc in query.column_descriptions:
if desc['type'] is User:
entity = desc['entity']
query = query.filter(entity.deleted == False)
return query
當bake_ok
設定為 True 時,事件鉤子將僅被呼叫一次,並且不會為正在被快取的特定查詢的後續呼叫呼叫。
從版本 1.3.11 開始:- 在QueryEvents.before_compile()
事件中新增了“bake_ok”標誌,並且如果未設定此標誌,則不允許透過“baked”擴充套件快取返回新的Query
物件的事件處理程式發生。
另請參閱
QueryEvents.before_compile_update()
QueryEvents.before_compile_delete()
使用 before_compile 事件
method before_compile_delete(query: Query, delete_context: BulkDelete) → None
允許在Query.delete()
中對Query
物件進行修改。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeQuery, 'before_compile_delete')
def receive_before_compile_delete(query, delete_context):
"listen for the 'before_compile_delete' event"
# ... (event handling logic) ...
自 1.4 版棄用:QueryEvents.before_compile_delete()
事件已被更加強大的SessionEvents.do_orm_execute()
鉤子所取代。
與QueryEvents.before_compile()
事件類似,此事件應配置為retval=True
,並返回修改後的Query
物件,如下所示:
@event.listens_for(Query, "before_compile_delete", retval=True)
def no_deleted(query, delete_context):
for desc in query.column_descriptions:
if desc['type'] is User:
entity = desc['entity']
query = query.filter(entity.deleted == False)
return query
引數:
-
query
– 一個Query
例項;這也是給定“刪除上下文”物件的.query
屬性。 -
delete_context
– 一個“刪除上下文”物件,其型別與QueryEvents.after_bulk_delete.delete_context
中描述的物件相同。
自版本 1.2.17 起新增。
另請參閱
QueryEvents.before_compile()
QueryEvents.before_compile_update()
method before_compile_update(query: Query, update_context: BulkUpdate) → None
允許在Query.update()
中修改Query
物件。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeQuery, 'before_compile_update')
def receive_before_compile_update(query, update_context):
"listen for the 'before_compile_update' event"
# ... (event handling logic) ...
自 1.4 版棄用:QueryEvents.before_compile_update()
事件已被更加強大的SessionEvents.do_orm_execute()
鉤子所取代。
與QueryEvents.before_compile()
事件類似,如果要使用該事件來修改Query
物件,則應將其配置為retval=True
,並返回修改後的Query
物件,如下所示:
@event.listens_for(Query, "before_compile_update", retval=True)
def no_deleted(query, update_context):
for desc in query.column_descriptions:
if desc['type'] is User:
entity = desc['entity']
query = query.filter(entity.deleted == False)
update_context.values['timestamp'] = datetime.utcnow()
return query
“更新上下文”物件的.values
字典也可以像上面示例中那樣就地修改。
引數:
-
query
– 一個Query
例項;這也是給定“更新上下文”物件的.query
屬性。 -
update_context
– 一個“更新上下文”物件,與QueryEvents.after_bulk_update.update_context
中描述的物件型別相同。物件具有在 UPDATE 上下文中的一個.values
屬性,該屬性是傳遞給Query.update()
的引數字典。此字典可以修改以更改結果 UPDATE 語句的 VALUES 子句。
版本 1.2.17 中的新功能。
另請參閱
QueryEvents.before_compile()
QueryEvents.before_compile_delete()
attribute dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.QueryEventsDispatch object>
回溯到 _Dispatch 類。
對 _Dispatch._events 進行雙向處理
儀器化事件
定義了 SQLAlchemy 的類儀器化系統。
此模組通常不直接對使用者應用程式可見,但定義了 ORM 互動的大部分內容。
instrumentation.py 處理終端使用者類的註冊以進行狀態跟蹤。它與 state.py 和 attributes.py 密切互動,分別為每個例項和每個類屬性儀器化。
類儀器化系統可以使用 sqlalchemy.ext.instrumentation
模組在每個類或全域性基礎上進行自定義,該模組提供了構建和指定替代儀器化形式的方法。
物件名稱 | 描述 |
---|---|
InstrumentationEvents | 與類儀器化事件相關的事件。 |
class sqlalchemy.orm.InstrumentationEvents
與類儀器化事件相關的事件。
這裡的監聽器支援針對任何新樣式類(即任何型別的子類為 'type')建立,然後對該類的事件將被觸發。如果將“propagate=True”標誌傳遞給 event.listen(),則該事件也將對該類的子類觸發。
Python 的 type
內建函式也被接受為目標,當使用時會導致為所有類發出事件。
注意這裡的“propagate”標誌預設為True
,與其他類級事件不同,預設為False
。這意味著當在超類上建立監聽器時,新的子類也將成為這些事件的物件。
成員
attribute_instrument(), class_instrument(), class_uninstrument(), dispatch
類簽名
類 sqlalchemy.orm.InstrumentationEvents
(sqlalchemy.event.Events
)
method attribute_instrument(cls: ClassManager[_O], key: _KT, inst: _O) → None
當屬性被儀器化時呼叫。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeBaseClass, 'attribute_instrument')
def receive_attribute_instrument(cls, key, inst):
"listen for the 'attribute_instrument' event"
# ... (event handling logic) ...
method class_instrument(cls: ClassManager[_O]) → None
在給定類被檢測之後呼叫。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeBaseClass, 'class_instrument')
def receive_class_instrument(cls):
"listen for the 'class_instrument' event"
# ... (event handling logic) ...
要獲取ClassManager
,請使用manager_of_class()
。
method class_uninstrument(cls: ClassManager[_O]) → None
在給定類被取消檢測之前呼叫。
示例引數形式:
from sqlalchemy import event
@event.listens_for(SomeBaseClass, 'class_uninstrument')
def receive_class_uninstrument(cls):
"listen for the 'class_uninstrument' event"
# ... (event handling logic) ...
要獲取ClassManager
,請使用manager_of_class()
。
attribute dispatch: _Dispatch[_ET] = <sqlalchemy.event.base.InstrumentationEventsDispatch object>
參考回 _Dispatch 類。
雙向反對 _Dispatch._events