1. transaction.on_commit()
是什麼?
這是一個回調註冊方法,在Django中用於在資料庫交易成功提交之後執行某些操作。
from django.db import transaction
transaction.on_commit(my_function)
執行這段代碼後,my_function()
將在當前交易成功結束後執行。
2. 什麼情況下使用?
情況 | 使用情況 |
---|---|
希望在DB保存確定結束後執行某些操作時 | ✅ 合適 |
希望在交易之後執行Celery任務時 | ✅ 合適 |
外部API調用、緩存更新等 | ✅ 合適 |
在交易外調用的順序不重要時 | ❌ 不合適 |
3. 核心概念
on_commit()
僅在「當前執行的交易存在時」才有意義。- 如果沒有交易,回調將立即執行!
4. 錯誤示例
def my_view(request):
def notify():
print("已執行!")
transaction.on_commit(notify) # 由於沒有交易,立即執行!
5. 正確使用示例
from django.db import transaction
def my_view(request):
with transaction.atomic():
post = Post.objects.create(...)
post.categories.add(...)
def translate():
translate_post.delay(post.id)
transaction.on_commit(translate)
在上述示例中,只有在post
創建和類別添加完成後,translate()
才會被執行。
6. 為什麼重要?
許多開發者會混淆以下概念:
- ORM的
create()
、add()
實際上並未提交 - 在提交之前,所有操作均為“邏輯保存”狀態
- Celery任務在獨立進程中執行,
- 如果在提交之前執行,將參考不完整的數據
7. 與Celery共同使用的理想示例
@shared_task
def post_finalize_task(post_id, categories, tags):
post = Post.objects.get(id=post_id)
with transaction.atomic():
for name in categories:
cat, _ = Category.objects.get_or_create(name=name)
post.categories.add(cat)
for name in tags:
tag, _ = Tag.objects.get_or_create(name=name)
post.tags.add(tag)
def schedule_translation():
translate_post.delay(post.id)
transaction.on_commit(schedule_translation)
這個結構確保了只有在類別/標籤保存確定之後才執行translate_post
任務。
8. 總結
概念 | 介紹 |
---|---|
何時執行? | 交易成功提交之後 |
失敗時? | rollback時絕對不執行 |
沒有交易時呢? | 立即執行(注意!) |
使用位置 | with transaction.atomic() 區塊內部 |
活用示例 | 執行Celery任務、發送通知、更新緩存等 |
9. Jesse的評論
transaction.on_commit()
並不僅僅是簡單的延遲執行。
這清晰表達了開發者僅在交易成功的情況下執行的意圖,
是使用ORM和異步處理時必不可少的工具,以保護數據完整性。
Add a New Comment