Communitygithub.com

django-celery

Django + Celery 非同期タスクパターン — 設定、タスク設計、Beat スケジューリング、リトライ、Canvas ワークフロー、モニタリング、テスト。Django アプリにバックグラウンドジョブ、定期タスク、非同期処理を追加する場合に使用します。

django-celery とは?

このスキルは、Django アプリケーションに本番品質の非同期タスク処理を Celery を用いて導入するための包括的なガイドです。Redis や RabbitMQ をブローカーとして、設定、タスクデザインパターン(基本タスク、リトライ可能、べき等、ソフトタイムリミット)、Celery Beat による定期実行、Canvas 機能によるチェーンやグループ処理、エラーハンドリング(デッドレターキュー)、テスト戦略(単体テスト、統合テスト、リトライテスト)、モニタリング(Flower など)までをカバーします。特に、Django モデルインスタンスをタスクに渡さない、タスクをべき等にするなどのアンチパターン回避策も詳述されており、実践的な知見が詰まっています。Flower、Sentry との統合、本番運用チェックリストも含まれており、Django 開発者がすぐに本番適用できる設計とコード例を提供します。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/django-celery

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Django + Celery 非同期タスクパターン

Redis または RabbitMQ を使用し、Django で Celery を使ったバックグラウンドタスク処理を行うための本番品質パターン。

いつアクティブにするか

  • Django アプリにバックグラウンドジョブや非同期処理を追加する場合
  • 定期的/スケジュールタスクを実装する場合
  • リクエストサイクルから低速な処理(メール、PDF 生成、API 呼び出し)をオフロードする場合
  • Celery Beat を cron ライクなスケジューリングに設定する場合
  • タスクの失敗、リトライ、キュー滞留のデバッグを行う場合
  • Celery タスクのテストを作成する場合

プロジェクトセットアップ

インストール

pip install 'celery[redis]' django-celery-results django-celery-beat

celery.py — アプリエントリポイント

# config/celery.py
import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.development')

app = Celery('myproject')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()  # INSTALLED_APP 内の tasks.py を自動検出

@app.task(bind=True, ignore_result=True)
def debug_task(self):
    print(f'Request: {self.request!r}')
# config/__init__.py
from .celery import app as celery_app

__all__ = ('celery_app',)

Django 設定

# config/settings/base.py

# ブローカー(本番では Redis 推奨)
CELERY_BROKER_URL = env('CELERY_BROKER_URL', default='redis://localhost:6379/0')
CELERY_RESULT_BACKEND = env('CELERY_RESULT_BACKEND', default='django-db')

# シリアライゼーション
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'

# タスク動作
CELERY_TASK_TRACK_STARTED = True
CELERY_TASK_TIME_LIMIT = 30 * 60        # ハードリミット: 30分
CELERY_TASK_SOFT_TIME_LIMIT = 25 * 60   # ソフトリミット: SoftTimeLimitExceeded を送信
CELERY_WORKER_PREFETCH_MULTIPLIER = 1   # ワーカーが長時間タスクを自分張りしないようにする
CELERY_TASK_ACKS_LATE = True            # ワーカークラッシュ時にキューに再投入

# 結果の永続化
CELERY_RESULT_EXPIRES = 60 * 60 * 24   # 結果を24時間保持

# Beat スケジューラー(定期タスク用)
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'

# インストール済みアプリ
INSTALLED_APPS += [
    'django_celery_results',
    'django_celery_beat',
]

ワーカーの実行

# ワーカー起動(開発環境)
celery -A config worker --loglevel=info

# Beat スケジューラー起動(定期タスク)
celery -A config beat --loglevel=info --scheduler django_celery_beat.schedulers:DatabaseScheduler

# ワーカー + Beat の統合(開発環境のみ、本番では非推奨)
celery -A config worker --beat --loglevel=info

# 本番: 複数ワーカー、同時実行数指定
celery -A config worker --loglevel=warning --concurrency=4 -Q default,high_priority

タスクデザインパターン

基本タスク

# apps/notifications/tasks.py
from celery import shared_task
import logging

logger = logging.getLogger(__name__)

@shared_task(name='notifications.send_welcome_email')
def send_welcome_email(user_id: int) -> None:
    """新規登録ユーザーにウェルカムメールを送信します。"""
    from apps.users.models import User
    from apps.notifications.services import EmailService

    try:
        user = User.objects.get(pk=user_id)
    except User.DoesNotExist:
        logger.warning('send_welcome_email: user %s not found', user_id)
        return  # べき等 — 例外を投げず、タスクはすでに完了不可能

    EmailService.send_welcome(user)
    logger.info('Welcome email sent to user %s', user_id)

リトライ可能なタスク

@shared_task(
    bind=True,
    name='integrations.sync_to_crm',
    max_retries=5,
    default_retry_delay=60,       # 初回リトライまでの秒数
    autoretry_for=(ConnectionError, TimeoutError),
    retry_backoff=True,           # 指数バックオフ
    retry_backoff_max=600,        # 最大10分でキャップ
    retry_jitter=True,            # ランダム化して群集効果を回避
)
def sync_contact_to_crm(self, contact_id: int) -> dict:
    """一時的な障害がある場合、外部CRMに連絡先をリトライ付きで同期します。"""
    from apps.crm.services import CRMClient

    try:
        result = CRMClient().sync(contact_id)
        return result
    except CRMClient.RateLimitError as exc:
        # レスポンスヘッダーからの具体的なリトライ遅延
        raise self.retry(exc=exc, countdown=int(exc.retry_after))

べき等タスクパターン

同じ入力を何度実行しても安全なタスクを設計します:

@shared_task(name='orders.mark_shipped')
def mark_order_shipped(order_id: int, tracking_number: str) -> None:
    """注文を発送済みにマーク — 複数回実行しても安全。"""
    from apps.orders.models import Order

    updated = Order.objects.filter(
        pk=order_id,
        status=Order.Status.PROCESSING,    # ガード: すでに発送済みでない場合のみ更新
    ).update(
        status=Order.Status.SHIPPED,
        tracking_number=tracking_number,
    )

    if not updated:
        logger.info('mark_order_shipped: order %s already shipped or not found', order_id)

ソフトタイムリミット付きタスク

from celery.exceptions import SoftTimeLimitExceeded

@shared_task(
    bind=True,
    name='reports.generate_pdf',
    soft_time_limit=120,
    time_limit=150,
)
def generate_pdf_report(self, report_id: int) -> str:
    """タイムアウトを適切に処理してPDFレポートを生成します。"""
    from apps.reports.services import PDFGenerator

    try:
        path = PDFGenerator.build(report_id)
        return path
    except SoftTimeLimitExceeded:
        # 強制終了前に部分ファイルをクリーンアップ
        PDFGenerator.cleanup(report_id)
        raise

タスクの呼び出し

from datetime import timedelta
from django.utils import timezone

# 非同期実行(fire-and-forget)
send_welcome_email.delay(user.pk)

# 将来のスケジュール
send_reminder.apply_async(args=[user.pk], countdown=3600)  # 1時間後
send_reminder.apply_async(args=[user.pk], eta=timezone.now() + timedelta(days=1))

# キュールーティング付き
sync_contact_to_crm.apply_async(args=[contact.pk], queue='high_priority')

# 同期的に実行(テスト/デバッグのみ)
result = generate_pdf_report.apply(args=[report.pk])

Beat スケジューリング(定期タスク)

コード定義スケジュール

# config/settings/base.py
from celery.schedules import crontab

CELERY_BEAT_SCHEDULE = {
    'cleanup-expired-sessions': {
        'task': 'users.cleanup_expired_sessions',
        'schedule': crontab(hour=2, minute=0),   # 毎日午前2時
    },
    'sync-inventory': {
        'task': 'products.sync_inventory',
        'schedule': 60.0,                         # 60秒ごと
    },
    'weekly-digest': {
        'task': 'notifications.send_weekly_digest',
        'schedule': crontab(day_of_week='monday', hour=8, minute=0),
    },
}

データベース定義スケジュール(django-celery-beat 経由)

# Django 管理画面またはコードから定期タスクを管理
from django_celery_beat.models import PeriodicTask, CrontabSchedule
import json

schedule, _ = CrontabSchedule.objects.get_or_create(
    hour='*/6', minute='0',
    timezone='UTC',
)

PeriodicTask.objects.update_or_create(
    name='Sync inventory every 6 hours',
    defaults={
        'crontab': schedule,
        'task': 'products.sync_inventory',
        'args': json.dumps([]),
        'enabled': True,
    }
)

Canvas: タスクのチェーンとグループ化

from celery import chain, group, chord

# チェーン: 結果を渡しながら順次実行
pipeline = chain(
    fetch_data.s(source_id),
    transform_data.s(),          # fetch_data の結果を最初の引数として受け取る
    load_to_warehouse.s(),
)
pipeline.delay()

# グループ: 並列実行
parallel = group(
    send_welcome_email.s(user_id)
    for user_id in new_user_ids
)
parallel.delay()

# Chord: 並列タスク + 全て完了時のコールバック
result = chord(
    group(process_chunk.s(chunk) for chunk in data_chunks),
    aggregate_results.s(),       # チャンク結果のリストで呼び出される
)
result.delay()

エラーハンドリングとデッドレターキュー

# apps/core/tasks.py
from celery.signals import task_failure

@task_failure.connect
def on_task_failure(sender, task_id, exception, args, kwargs, traceback, einfo, **kw):
    """すべてのタスク失敗を Sentry / アラートに記録します。"""
    import sentry_sdk
    with sentry_sdk.new_scope() as scope:
        scope.set_context('celery', {
            'task': sender.name,
            'task_id': task_id,
            'args': args,
            'kwargs': kwargs,
        })
        sentry_sdk.capture_exception(exception)
# 最大リトライ後の失敗タスクをデッドレターキューにルーティング
@shared_task(
    bind=True,
    max_retries=3,
    name='payments.charge_card',
)
def charge_card(self, order_id: int) -> None:
    from apps.payments.models import Order, FailedCharge

    try:
        _do_charge(order_id)
    except Exception as exc:
        if self.request.retries >= self.max_retries:
            # 手動レビュー用にデッドレターテーブルに永続化
            FailedCharge.objects.create(
                order_id=order_id,
                error=str(exc),
                task_id=self.request.id,
            )
            return  # 例外を投げない — タスクは完全に失敗
        raise self.retry(exc=exc)

Celery タスクのテスト

単体テスト(ブローカーなし)

# tests/test_tasks.py
import pytest
from unittest.mock import patch, MagicMock
from apps.notifications.tasks import send_welcome_email

class TestSendWelcomeEmail:

    @pytest.mark.django_db
    def test_sends_email_to_existing_user(self, user):
        with patch('apps.notifications.services.EmailService') as mock_email:
            send_welcome_email(user.pk)
            mock_email.send_welcome.assert_called_once_with(user)

    @pytest.mark.django_db
    def test_skips_missing_user_gracefully(self):
        """エンキューと実行の間でユーザーが削除された場合に例外を投げない。"""
        send_welcome_email(99999)  # 存在しないユーザー — 例外を投げてはならない

CELERY_TASK_ALWAYS_EAGER を使用した統合テスト

# config/settings/test.py
CELERY_TASK_ALWAYS_EAGER = True      # テストでは同期的にタスク実行
CELERY_TASK_EAGER_PROPAGATES = True  # タスクからの例外を再スロー

# tests/test_integration.py
@pytest.mark.django_db
def test_registration_triggers_welcome_email(client):
    with patch('apps.notifications.services.EmailService') as mock_email:
        response = client.post('/api/users/', {
            'email': '[email protected]',
            'password': 'strongpass123',
        })

    assert response.status_code == 201
    mock_email.send_welcome.assert_called_once()

リトライのテスト

@pytest.mark.django_db
def test_task_retries_on_connection_error():
    with patch('apps.crm.services.CRMClient.sync') as mock_sync:
        mock_sync.side_effect = ConnectionError('timeout')

        with pytest.raises(ConnectionError):
            sync_contact_to_crm.apply(args=[1], throw=True)

        assert mock_sync.call_count == 1  # Eager モードでは最初の試行のみ

モニタリング

# アクティブなワーカーとキューを調査
celery -A config inspect active
celery -A config inspect stats
celery -A config inspect reserved

# キューの長さを確認(Redis)
redis-cli llen celery

# Flower: Web ベースのリアルタイムモニター
pip install flower
celery -A config flower --port=5555

アンチパターン

# 悪い例: モデルインスタンスを渡す — 実行時に古くなっている可能性あり
send_welcome_email.delay(user)        # ORM オブジェクトを決して渡さない
send_welcome_email.delay(user.pk)     # 常に PK を渡す

# 悪い例: 本番ビューでタスクを同期的に呼び出す
result = generate_report.apply()      # リクエストスレッドをブロック

# 悪い例: ガードのない非べき等タスク
@shared_task
def charge_and_fulfill(order_id):
    order.charge()     # タスクがリトライされた場合、二重に課金される可能性あり!
    order.fulfill()

# 良い例: ステータスガードによるべき等
@shared_task
def charge_and_fulfill(order_id):
    order = Order.objects.select_for_update().get(pk=order_id)
    if order.status != Order.Status.PENDING:
        return  # すでに処理済み
    order.charge()
    order.fulfill()

本番チェックリスト

確認項目設定
ワーカーのクラッシュ時に再起動supervisord または systemd ユニット
CELERY_TASK_ACKS_LATE = Trueワーカークラッシュ時にキューに再投入
CELERY_WORKER_PREFETCH_MULTIPLIER = 1長時間タスクの公平な分散
優先度ごとに個別キュー-Q default,high_priority,low_priority
CELERY_TASK_SOFT_TIME_LIMIT 設定強制終了前のグレースフルタイムアウト
Sentry 統合すべての task_failure シグナルを取得
Flower または他のモニターキューの深さを可視化
Beat は単一ノードのみで実行重複した定期タスク実行を防止

関連スキル

  • django-patterns — ORM、サービス層、プロジェクト構造
  • django-tdd — Django モデル、ビュー、サービスのテスト
  • python-testing — pytest の設定とフィクスチャ

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

関連スキル