Communitygithub.com

django-celery

Django + Celery 异步任务模式——配置、任务设计、定时调度、重试、工作流编排、监控与测试。适用于为 Django 应用添加后台作业、定时任务或异步处理。

django-celery 是什么?

该技能提供了一套生产级的 Django + Celery 异步任务处理模式,支持 Redis 或 RabbitMQ 作为消息代理。它涵盖了从项目初始化(包括 celery.py 入口点、Django 设置配置)、任务设计模式(基础任务、可重试任务、幂等任务、软时间限制任务)到任务调用、定时调度(代码定义与数据库定义)、工作流编排(链、组、和弦)的完整流程。此外,技能还详细介绍了错误处理与死信队列机制、单元测试与集成测试方法(包括 CELERY_TASK_ALWAYS_EAGER 模式)、监控(Flower、redis-cli)以及常见反模式和生成环境检查清单。该技能适用于任何需要为 Django 应用添加后台作业、定时任务或异步处理的开发者,并支持 Cursor、Claude Code 等 AI 编码助手。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/django-celery

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Django + Celery 异步任务模式

使用 Celery 搭配 Redis 或 RabbitMQ,在 Django 中进行生产级后台任务处理。

何时激活

  • 为 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'请求: {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   # 防止 worker 囤积长时间任务
CELERY_TASK_ACKS_LATE = True            # worker 崩溃时重新入队

# 结果持久化
CELERY_RESULT_EXPIRES = 60 * 60 * 24   # 结果保留 24 小时

# Beat 调度器(用于定期任务)
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'

# 已安装的应用
INSTALLED_APPS += [
    'django_celery_results',
    'django_celery_beat',
]

运行 Worker

# 启动 worker(开发环境)
celery -A config worker --loglevel=info

# 启动 beat 调度器(定期任务)
celery -A config beat --loglevel=info --scheduler django_celery_beat.schedulers:DatabaseScheduler

# 合并 worker + beat(仅开发环境,绝不能用于生产)
celery -A config worker --beat --loglevel=info

# 生产环境:多 worker 带并发
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: 用户 %s 未找到', user_id)
        return  # 幂等 — 不抛出异常,任务已经无法完成

    EmailService.send_welcome(user)
    logger.info('欢迎邮件已发送给用户 %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: 订单 %s 已发货或未找到', 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

# 触发并忘记(异步)
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='每 6 小时同步库存',
    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()

# 和弦:并行任务 + 全部完成后回调
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 模式下仅第一次尝试

监控

# 检查活动的 worker 和队列
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)     # 始终传递主键

# 错误:在生产视图中同步调用任务
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()

生产环境检查清单

检查项设置
Worker 崩溃后自动重启supervisord 或 systemd 单元
CELERY_TASK_ACKS_LATE = TrueWorker 崩溃时重新入队任务
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 配置和 fixtures

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/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

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.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

相关技能