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.
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()
enadd()
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.
댓글이 없습니다.