1. Wat is transaction.on_commit()?

Dit is een callback registratie methode die gebruikt wordt wanneer je bepaalde taken wilt uitvoeren direct na een succesvolle commit van een database transactie in Django.

from django.db import transaction

transaction.on_commit(my_function)

Wanneer je deze code uitvoert, zal my_function() worden uitgevoerd nadat de huidige transactie succesvol is voltooid.

Django transaction.on_commit conceptuele afbeelding


2. In welke situaties gebruik je het?

Situatie Gebruik
Wanneer je iets wilt uitvoeren nadat de opslag in de DB zeker is voltooid ✅ Geschikt
Wanneer je een Celery taak na de transactie wilt uitvoeren ✅ Geschikt
Buitenlandse API-aanroepen, cache-updates, etc. ✅ Geschikt
Wanneer de volgorde van aanroepen buiten de transactie niet belangrijk is ❌ Ongeschikt

3. Kernconcepten

  • on_commit() heeft alleen betekenis als er een actieve transactie is.
  • Als er geen transactie is, wordt de callback onmiddellijk uitgevoerd!

4. Foutief voorbeeld

def my_view(request):
    def notify():
        print("Uitgevoerd!")

    transaction.on_commit(notify)  # Aangezien er geen transactie is, wordt dit onmiddellijk uitgevoerd!

5. Correct gebruik voorbeeld

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)

In dit voorbeeld wordt translate() alleen uitgevoerd nadat zowel de creatie van de post als de toevoeging van categorieën is voltooid.


6. Waarom is het belangrijk?

Veel ontwikkelaars verwarren het volgende:

  • De create() en add() methoden van ORM zijn in werkelijkheid nog niet gecommit
  • Voor de commit zijn ze allemaal in "logische opslag" status
  • Celery-taken draaien in een apart proces,
  • Wanneer ze worden uitgevoerd vóór de commit, verwijzen ze naar onvolledige data

7. Ideaal voorbeeld van gebruik met 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)

Deze structuur garandeert dat de taak translate_post alleen wordt uitgevoerd nadat de opslag van de categorieën/tags zeker is.


8. Samenvatting

Concept Uitleg
Wanneer voert het uit? Direct na een succesvolle commit van de transactie
Bij mislukking? Bij rollback zal het absoluut niet worden uitgevoerd
Als er geen transactie is? Wordt onmiddellijk uitgevoerd (let op!)
Gebruik locatie Binnen een with transaction.atomic() blok
Toepassingsvoorbeeld Uitvoeren van Celery-taken, verzenden van meldingen, cache-updates, enz.

9. Opmerkingen van Jesse

transaction.on_commit() is geen eenvoudige vertraagde uitvoering.
Het is een duidelijke uitdrukking van de intentie van de ontwikkelaar om alleen uit te voeren als de transactie succesvol is, en is een noodzakelijk hulpmiddel voor het handhaven van gegevensintegriteit wanneer ORM en asynchrone verwerking samen worden gebruikt.