mcpField
D
django-patterns

django-patterns

github.com/rohitg00开发2.8k181 次安装24 周前更新
代码仓库

关于 django-patterns

面向 Django 开发者的模式指南,涵盖项目分层、ORM 查询优化、REST Framework 序列化器及中间件。还说明信号的使用边界,并列出常见反模式与测试检查项。

主要功能

  1. 01项目结构与业务逻辑分层
  2. 02select_related 与 prefetch_related
  3. 03REST Framework 序列化器
  4. 04跨应用副作用与信号
  5. 05自定义中间件模式
  6. 06反模式与测试检查项

适用场景

  1. 01规划 Django 项目模块结构
  2. 02减少 ORM 查询中的 N+1 问题
  3. 03设计 API 序列化与输入验证
  4. 04检查视图、信号及测试实践

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/rohitg00/awesome-claude-code-toolkit --skill django-patterns

安装后在 Claude Code 中输入/django-patterns确认已加载。

详细介绍

Django 模式

项目结构

将 Django 项目组织为应用、共享实用工具和配置清晰分离的结构。

project/
  config/
    settings/
      base.py
      local.py
      production.py
    urls.py
    wsgi.py
  apps/
    users/
      models.py
      serializers.py
      views.py
      services.py
      selectors.py
      urls.py
      tests/
    orders/
      ...
  common/
    models.py
    permissions.py
    pagination.py

将业务逻辑放在 services.py(写操作)和 selectors.py(读操作)中。视图应保持精简。

ORM 优化

# select_related for ForeignKey / OneToOne (SQL JOIN)
orders = Order.objects.select_related("customer", "customer__profile").all()

# prefetch_related for ManyToMany / reverse FK (separate query)
authors = Author.objects.prefetch_related(
    Prefetch("books", queryset=Book.objects.filter(published=True))
).all()

# Defer fields you don't need
posts = Post.objects.defer("body", "metadata").filter(status="published")

# Use .only() when you need just a few columns
emails = User.objects.only("id", "email").filter(is_active=True)

# Bulk operations
Product.objects.bulk_create(products, batch_size=1000)
Product.objects.bulk_update(products, ["price", "stock"], batch_size=1000)

始终在测试中使用 django-debug-toolbar 或 connection.queries 检查查询。

Django REST Framework 序列化器

class OrderSerializer(serializers.ModelSerializer):
    customer_name = serializers.CharField(source="customer.full_name", read_only=True)
    items = OrderItemSerializer(many=True, read_only=True)
    total = serializers.SerializerMethodField()

    class Meta:
        model = Order
        fields = ["id", "customer_name", "items", "total", "created_at"]
        read_only_fields = ["id", "created_at"]

    def get_total(self, obj):
        return sum(item.price * item.quantity for item in obj.items.all())

    def validate(self, data):
        if data.get("start_date") and data.get("end_date"):
            if data["start_date"] >= data["end_date"]:
                raise serializers.ValidationError("end_date must be after start_date")
        return data

信号

from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=Order)
def order_created_handler(sender, instance, created, **kwargs):
    if created:
        send_order_confirmation.delay(instance.id)
        update_inventory.delay(instance.id)

跨应用的副作用优先使用信号。同一应用内的逻辑应直接调用服务。

自定义中间件

import time
import logging

logger = logging.getLogger(__name__)

class RequestTimingMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        start = time.monotonic()
        response = self.get_response(request)
        duration = time.monotonic() - start
        logger.info(f"{request.method} {request.path} {response.status_code} {duration:.3f}s")
        return response

反模式

  • 将业务逻辑放在视图或序列化器中,而非服务层
  • 在列表端点中使用 Model.objects.all(),却不进行分页
  • 未使用 select_related / prefetch_related 导致 N+1 查询
  • 在同一应用内的逻辑中过度使用信号(会让执行流程难以追踪)
  • 将密钥存储在 settings.py 中,而非环境变量中
  • 执行原始 SQL 时未使用参数化查询

检查清单

  • 业务逻辑放在服务或选择器中,而非视图中
  • 所有列表查询都在需要时使用 select_related 或 prefetch_related
  • 序列化器使用自定义 validate 方法验证输入数据
  • 设置拆分为 base/local/production 模块
  • 合并前审查迁移
  • 批量插入/更新使用批量操作
  • 自定义中间件遵循 WSGI 可调用对象模式
  • 测试覆盖模型约束、序列化器验证和视图权限

评论

支持 Markdown