python / expert
Snippet
Django Signal-Handler mit Transaktions-Atomic
Django-Signale ermöglichen entkoppelte Kommunikation zwischen Komponenten. Dieses Expertenmuster verwendet post_save, um Aktionen auszulösen, nachdem eine Bestellung erstellt wurde. Der transaction.atomic-Kontextmanager stellt sicher, dass alle Datenbankoperationen gemeinsam erfolgreich sind oder fehlschlagen, was partielle Updates verhindert wie das Bestätigen einer Bestellung ohne Bestandsreservierung. Die Prüfung des Produktbestands verhindert Überverkäufe in einer gleichzeitigen Umgebung.
snippet.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from django.db import models, transactionfrom django.db.models.signals import post_savefrom django.dispatch import receiverfrom django.core.mail import send_mailfrom django.conf import settings@receiver(post_save, sender='orders.Order')def order_created_handler(sender, instance, created, **kwargs):if not created:returnwith transaction.atomic(savepoint=True):order = instanceorder.status = 'confirmed'order.save(update_fields=['status', 'updated_at'])for item in order.items.select_related('product'):product = item.productproduct.stock -= item.quantityif product.stock < 0:raise ValueError(f'Insufficient stock for {product.name}')product.save(update_fields=['stock'])send_mail(subject=f'Order #{order.id} Confirmed',message=f'Your order has been confirmed and is being processed.',from_email=settings.DEFAULT_FROM_EMAIL,recipient_list=[order.customer.email],fail_silently=False,)
django
Erklärung
1
@receiver(post_save, sender='orders.Order')
Registriert den Signalempfänger für das post_save-Ereignis des Order-Modells
2
if not created: return
Überspringt die Verarbeitung für Updates, behandelt nur neue Bestellerstellung
3
with transaction.atomic(savepoint=True):
Ummantelt alle Datenbankänderungen in einer Transaktion mit Savepoint-Unterstützung
4
update_fields=['status', 'updated_at']
Aktualisiert nur bestimmte Spalten, um vollständige Zeilensperren zu vermeiden
5
select_related('product')
Verhindert N+1-Abfragen beim Zugriff auf das Produkt von jedem Bestellposten
6
if product.stock < 0: raise ValueError(...)
Geschäftsregel-Durchsetzung innerhalb der atomaren Transaktion