ベストプラクティス
ベストプラクティス
Section titled “ベストプラクティス”Djangoでの正しい構造とベストプラクティスを詳しく解説します。
1. Outboxパターンの実装
Section titled “1. Outboxパターンの実装”from django.db import models, transaction
class OutboxEvent(models.Model): event_type = models.CharField(max_length=100) aggregate_id = models.CharField(max_length=100) payload = models.JSONField() status = models.CharField(max_length=50, default='PENDING') retry_count = models.IntegerField(default=0)
@transaction.atomicdef create_order(order_data): # ✅ 正しい: トランザクション内でOutboxに記録 order = Order.objects.create(**order_data)
# Outboxテーブルに外部API呼び出しのタスクを記録 OutboxEvent.objects.create( event_type='PAYMENT_CHARGE', aggregate_id=str(order.id), payload={ 'orderId': order.id, 'amount': order_data['amount'], }, status='PENDING', )
return order
# 別のプロセス/ワーカーでOutboxを処理from celery import Celery
celery_app = Celery('tasks', broker='redis://localhost:6379')
@celery_app.taskdef process_outbox(): pending_events = OutboxEvent.objects.filter(status='PENDING')[:10]
for event in pending_events: try: # 外部APIを呼ぶ(トランザクション外) import requests response = requests.post( 'https://payment-api.example.com/charge', json=event.payload, )
if response.status_code == 200: event.status = 'COMPLETED' event.save() else: event.status = 'FAILED' event.retry_count += 1 event.save() except Exception as e: event.status = 'FAILED' event.retry_count += 1 event.save()なぜ正しいか:
- トランザクションの短縮: データベースのロック時間が短縮される
- 外部障害の分離: 外部APIの障害がトランザクションに影響しない
- 再実行の容易さ: Outboxテーブルから再実行可能
2. select_related/prefetch_relatedの使用
Section titled “2. select_related/prefetch_relatedの使用”# ✅ 正しい: select_relatedを使用して関連データを事前に読み込むdef get_orders(request): orders = Order.objects.select_related('user').prefetch_related('items').all() # 3回のクエリのみ: Order.objects.all(), User.where(id: ...), OrderItem.where(order_id: ...) return render(request, 'orders.html', {'orders': orders})なぜ正しいか:
- クエリ数の削減: 関連データを事前に読み込むことで、クエリ数が削減される
- パフォーマンスの向上: データベースへのアクセス回数が減少し、パフォーマンスが向上する
ベストプラクティスのポイント:
- Outboxパターン: トランザクション内で外部API呼び出しを記録し、別プロセスで処理
- select_related/prefetch_related: 関連データを事前に読み込む
適切なベストプラクティスの実装により、安全で信頼性の高いDjangoアプリケーションを構築できます。