1. transaction.on_commit()是什么?

这是在Django中,当想在数据库事务成功提交后执行某个操作时使用的回调注册方法.

from django.db import transaction

transaction.on_commit(my_function)

执行该代码后,只有在当前事务成功结束后,my_function()才会执行.

Django transaction.on_commit 概念图


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与异步处理时,维护数据完整性的重要工具.