You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何构建集成Celery、Channels、Stripe的生产级Django SaaS后端架构?

生产级类型安全Django SaaS项目结构与组件集成最佳实践

一、核心目录结构(严格遵循关注点分离)

saas_project/
├── config/                  # 集中配置层(配置、入口、核心服务初始化)
│   ├── __init__.py
│   ├── settings/           # 多环境配置拆分
│   │   ├── __init__.py
│   │   ├── base.py         # 通用基础配置
│   │   ├── development.py  # 开发环境专属配置
│   │   ├── production.py   # 生产环境专属配置
│   │   └── types.py        # 配置类型定义(类型安全核心)
│   ├── asgi.py             # Channels ASGI入口
│   ├── wsgi.py             # WSGI入口
│   └── celery.py           # Celery核心配置
├── apps/                   # 业务应用层(按模块高内聚拆分)
│   ├── __init__.py
│   ├── users/              # 用户模块(认证、订阅、通知)
│   │   ├── __init__.py
│   │   ├── models.py       # 带类型注解的模型
│   │   ├── serializers.py  # DRF序列化器(类型注解)
│   │   ├── views.py        # DRF视图/视图集(类型注解)
│   │   ├── tasks.py        # 用户相关异步任务
│   │   ├── consumers.py    # 用户WebSocket消费者
│   │   ├── stripe/         # Stripe集成子模块
│   │   │   ├── __init__.py
│   │   │   ├── webhooks.py # Stripe Webhook处理
│   │   │   └── services.py # Stripe业务逻辑封装
│   │   └── urls.py
│   └── core/               # 通用核心模块(工具、中间件)
│       ├── __init__.py
│       ├── middleware.py
│       └── utils.py
├── tasks/                  # 全局跨模块异步任务
│   ├── __init__.py
│   ├── background_tasks.py
│   └── types.py            # 任务类型定义
├── consumers/              # 全局跨模块WebSocket消费者
│   ├── __init__.py
│   ├── realtime.py
│   └── types.py            # 消费者消息类型定义
├── static/                 # 静态资源
├── media/                  # 媒体资源
├── docker-compose.yml      # Docker Compose服务编排
├── Dockerfile              # Django服务镜像构建
├── requirements/           # 分层依赖管理
│   ├── base.txt
│   ├── dev.txt
│   ├── prod.txt
│   └── types.txt           # 类型检查专属依赖
├── mypy.ini                # Mypy类型检查配置
└── manage.py

目录职责说明

  • config/:统一管理所有配置、服务入口,避免配置分散;单独维护类型定义确保配置安全
  • apps/:按业务模块拆分,每个模块内包含自身的模型、视图、任务、消费者,实现高内聚低耦合
  • tasks//consumers/:存放跨模块的全局任务与消费者,避免业务模块间的耦合
  • requirements/:分层管理依赖,将类型检查依赖单独拆分,便于环境切换

二、类型安全的配置体系

1. 用Pydantic Settings替代原生Django配置

在config/settings/types.py中定义类型化配置类,自动验证环境变量类型:

from pydantic_settings import BaseSettings, SettingsConfigDict
from typing import Optional, List

class Settings(BaseSettings):
    model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")

    # 基础配置
    DEBUG: bool = False
    SECRET_KEY: str
    ALLOWED_HOSTS: List[str] = []

    # PostgreSQL配置
    DB_NAME: str
    DB_USER: str
    DB_PASSWORD: str
    DB_HOST: str = "postgres"
    DB_PORT: int = 5432

    # Redis配置(Celery + Channels)
    REDIS_URL: str = "redis://redis:6379/0"

    # Celery配置
    CELERY_BROKER_URL: str = "redis://redis:6379/0"
    CELERY_RESULT_BACKEND: str = "redis://redis:6379/0"

    # Stripe配置
    STRIPE_SECRET_KEY: str
    STRIPE_PUBLISHABLE_KEY: str
    STRIPE_WEBHOOK_SECRET: str

settings = Settings()

2. 多环境配置映射

在config/settings/base.py中将Pydantic配置映射到Django原生配置:

from config.settings.types import settings

# 基础Django配置
DEBUG = settings.DEBUG
SECRET_KEY = settings.SECRET_KEY
ALLOWED_HOSTS = settings.ALLOWED_HOSTS

# 数据库配置
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": settings.DB_NAME,
        "USER": settings.DB_USER,
        "PASSWORD": settings.DB_PASSWORD,
        "HOST": settings.DB_HOST,
        "PORT": settings.DB_PORT,
    }
}

# Celery配置
CELERY_BROKER_URL = settings.CELERY_BROKER_URL
CELERY_RESULT_BACKEND = settings.CELERY_RESULT_BACKEND

# Channels配置
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [settings.REDIS_URL],
        },
    },
}

# Stripe配置
STRIPE_SECRET_KEY = settings.STRIPE_SECRET_KEY
STRIPE_PUBLISHABLE_KEY = settings.STRIPE_PUBLISHABLE_KEY
STRIPE_WEBHOOK_SECRET = settings.STRIPE_WEBHOOK_SECRET

development.py和production.py继承base.py,仅覆盖环境差异配置(如DEBUG、ALLOWED_HOSTS)。

三、各组件集成实现

1. PostgreSQL集成

在Docker Compose中定义Postgres服务:

services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    ports:
      - "5432:5432"

2. Celery + Redis集成

  • 核心配置config/celery.py:
from celery import Celery
from django.conf import settings

app = Celery("saas_project")
app.config_from_object("django.conf:settings", namespace="CELERY")
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
  • Docker Compose添加Celery Worker和Beat服务:
celery_worker:
    build: .
    command: celery -A config worker --loglevel=info
    volumes:
      - .:/app
    depends_on:
      - postgres
      - redis

  celery_beat:
    build: .
    command: celery -A config beat --loglevel=info
    volumes:
      - .:/app
    depends_on:
      - postgres
      - redis
  • 任务添加类型注解:
# apps/users/tasks.py
from celery import shared_task
from typing import int
from apps.users.models import User

@shared_task
def send_welcome_email(user_id: int) -> None:
    user = User.objects.get(id=user_id)
    # 发送邮件逻辑
    pass

3. Django Channels集成

  • ASGI入口config/asgi.py:
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from django.urls import path, include

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

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack(
        URLRouter([
            path("ws/users/", include("apps.users.consumers.urls")),
            path("ws/realtime/", include("consumers.urls")),
        ])
    ),
})
  • 消费者添加类型注解:
# apps/users/consumers.py
from channels.generic.websocket import AsyncWebsocketConsumer
import json
from typing import Dict, Any

class UserNotificationConsumer(AsyncWebsocketConsumer):
    async def connect(self) -> None:
        await self.accept()

    async def receive(self, text_data: str) -> None:
        data: Dict[str, Any] = json.loads(text_data)
        # 消息处理逻辑
        await self.send(text_data=json.dumps({"message": "Received"}))

4. Stripe集成

  • 封装Stripe服务逻辑(带类型注解):
# apps/users/stripe/services.py
import stripe
from django.conf import settings
from typing import Any
from apps.users.models import User

stripe.api_key = settings.STRIPE_SECRET_KEY

def create_subscription(user: User, plan_id: str) -> stripe.Subscription:
    customer = stripe.Customer.create(email=user.email)
    subscription = stripe.Subscription.create(
        customer=customer.id,
        items=[{"price": plan_id}],
        payment_behavior="default_incomplete",
        expand=["latest_invoice.payment_intent"],
    )
    return subscription

def handle_stripe_event(event: stripe.Event) -> None:
    event_type = event.type
    if event_type == "customer.subscription.created":
        # 处理订阅创建逻辑
        pass
  • Webhook处理视图:
# apps/users/stripe/webhooks.py
from django.http import HttpResponse
from django.views.decorators.http import require_POST
from django.views.decorators.csrf import csrf_exempt
import stripe
from django.conf import settings
from apps.users.stripe.services import handle_stripe_event

@csrf_exempt
@require_POST
def stripe_webhook(request) -> HttpResponse:
    payload = request.body
    sig_header = request.META.get("HTTP_STRIPE_SIGNATURE")
    event: stripe.Event | None = None

    try:
        event = stripe.Webhook.construct_event(
            payload, sig_header, settings.STRIPE_WEBHOOK_SECRET
        )
    except (ValueError, stripe.error.SignatureVerificationError):
        return HttpResponse(status=400)

    if event:
        handle_stripe_event(event)
    return HttpResponse(status=200)

5. Docker & Docker Compose集成

  • Dockerfile示例:
FROM python:3.11-slim

WORKDIR /app

COPY requirements/base.txt requirements/dev.txt requirements/types.txt ./
RUN pip install --no-cache-dir -r base.txt -r dev.txt -r types.txt

COPY . .

EXPOSE 8000

CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
  • 完整Docker Compose包含所有服务:django、postgres、redis、celery_worker、celery_beat、flower(可选监控)。

四、类型安全保障措施

  • 全量类型注解:所有模型、视图、任务、消费者、服务函数都添加类型注解,包括参数、返回值、内部变量
  • Mypy配置:mypy.ini中启用Django、DRF、Celery、Channels的类型插件:
[mypy]
plugins = mypy_django_plugin.main, mypy_drf_plugin.main, celery.contrib.mypy
django_settings_module = config.settings.base
strict = True
  • 依赖管理:在requirements/types.txt中添加类型检查依赖:mypy, django-stubs, djangorestframework-stubs, celery-stubs, pydantic-settings
  • 配置验证:利用Pydantic Settings自动验证环境变量类型,避免配置错误

内容的提问来源于stack exchange,提问作者aburayhanalif

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.02 06:17:27