Skip to main content

django-patterns

Django 架构模式、使用 DRF 的 REST API 设计、ORM 最佳实践、缓存、信号(Signals)、中间件(Middleware)以及生产级 Django 应用。 Use when this capability is needed.

Zur Installation springen

Quellinformationen

Repository
tomevault-io/tomes
Letzte Quellaktivität
23. Juli 2026 um 21:48
Erkannte Sprache von SKILL.md
Chinesisch
Sterne
1
Forks
0

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
django-patterns
description
Django 架构模式、使用 DRF 的 REST API 设计、ORM 最佳实践、缓存、信号(Signals)、中间件(Middleware)以及生产级 Django 应用。 Use when this capability is needed.
metadata
{"author":"codelably"}
# Django 开发模式 适用于可扩展、可维护应用程序的生产级 Django 架构模式。 ## 何时激活 - 构建 Django Web 应用程序时 - 设计 Django REST Framework (DRF) API 时 - 处理 Django ORM 和模型时 - 设置 Django 项目结构时 - 实现缓存(Caching)、信号(Signals)、中间件(Middleware)时 ## 项目结构 ### 推荐布局 ``` myproject/ ├── config/ │ ├── __init__.py │ ├── settings/ │ │ ├── __init__.py │ │ ├── base.py # 基础设置 │ │ ├── development.py # 开发环境设置 │ │ ├── production.py # 生产环境设置 │ │ └── test.py # 测试环境设置 │ ├── urls.py │ ├── wsgi.py │ └── asgi.py ├── manage.py └── apps/ ├── __init__.py ├── users/ │ ├── __init__.py │ ├── models.py │ ├── views.py │ ├── serializers.py │ ├── urls.py │ ├── permissions.py │ ├── filters.py │ ├── services.py │ └── tests/ └── products/ └── ... ``` ### 分离设置模式(Split Settings Pattern) ```python # config/settings/base.py from pathlib import Path BASE_DIR = Path(__file__).resolve().parent.parent.parent SECRET_KEY = env('DJANGO_SECRET_KEY') DEBUG = False ALLOWED_HOSTS = [] INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'rest_framework.authtoken', 'corsheaders', # 本地应用 'apps.users', 'apps.products', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'config.urls' WSGI_APPLICATION = 'config.wsgi.application' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': env('DB_NAME'), 'USER': env('DB_USER'), 'PASSWORD': env('DB_PASSWORD'), 'HOST': env('DB_HOST'), 'PORT': env('DB_PORT', default='5432'), } } # config/settings/development.py from .base import * DEBUG = True ALLOWED_HOSTS = ['localhost', '127.0.0.1'] DATABASES['default']['NAME'] = 'myproject_dev' INSTALLED_APPS += ['debug_toolbar'] MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware'] EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' # config/settings/production.py from .base import * DEBUG = False ALLOWED_HOSTS = env.list('ALLOWED_HOSTS') SECURE_SSL_REDIRECT = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True SECURE_HSTS_SECONDS = 31536000 SECURE_HSTS_INCLUDE_SUBDOMAINS = True SECURE_HSTS_PRELOAD = True # 日志配置 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'file': { 'level': 'WARNING', 'class': 'logging.FileHandler', 'filename': '/var/log/django/django.log', }, }, 'loggers': { 'django': { 'handlers': ['file'], 'level': 'WARNING', 'propagate': True, }, }, } ``` ## 模型设计模式 ### 模型最佳实践 ```python from django.db import models from django.contrib.auth.models import AbstractUser from django.core.validators import MinValueValidator, MaxValueValidator class User(AbstractUser): """扩展 AbstractUser 的自定义用户模型。""" email = models.EmailField(unique=True) phone = models.CharField(max_length=20, blank=True) birth_date = models.DateField(null=True, blank=True) USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['username'] class Meta: db_table = 'users' verbose_name = 'user' verbose_name_plural = 'users' ordering = ['-date_joined'] def __str__(self): return self.email def get_full_name(self): return f"{self.first_name} {self.last_name}".strip() class Product(models.Model): """带有适当字段配置的产品模型。""" name = models.CharField(max_length=200) slug = models.SlugField(unique=True, max_length=250) description = models.TextField(blank=True) price = models.DecimalField( max_digits=10, decimal_places=2, validators=[MinValueValidator(0)] ) stock = models.PositiveIntegerField(default=0) is_active = models.BooleanField(default=True) category = models.ForeignKey( 'Category', on_delete=models.CASCADE, related_name='products' ) tags = models.ManyToManyField('Tag', blank=True, related_name='products') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: db_table = 'products' ordering = ['-created_at'] indexes = [ models.Index(fields=['slug']), models.Index(fields=['-created_at']), models.Index(fields=['category', 'is_active']), ] constraints = [ models.CheckConstraint( check=models.Q(price__gte=0), name='price_non_negative' ) ] def __str__(self): return self.name def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(self.name) super().save(*args, **kwargs) ``` ### QuerySet 最佳实践 ```python from django.db import models class ProductQuerySet(models.QuerySet): """Product 模型的自定义 QuerySet。""" def active(self): """仅返回已激活的产品。""" return self.filter(is_active=True) def with_category(self): """使用 select_related 加载分类,避免 N+1 查询。""" return self.select_related('category') def with_tags(self): """使用 prefetch_related 预加载多对多关系的标签。""" return self.prefetch_related('tags') def in_stock(self): """返回库存 > 0 的产品。""" return self.filter(stock__gt=0) def search(self, query): """按名称或描述搜索产品。""" return self.filter( models.Q(name__icontains=query) | models.Q(description__icontains=query) ) class Product(models.Model): # ... 字段 ... objects = ProductQuerySet.as_manager() # 使用自定义 QuerySet # 用法 Product.objects.active().with_category().in_stock() ``` ### 管理器(Manager)方法 ```python class ProductManager(models.Manager): """用于复杂查询的自定义管理器。""" def get_or_none(self, **kwargs): """返回对象,或者在不存在时返回 None 而不是抛出 DoesNotExist。""" try: return self.get(**kwargs) except self.model.DoesNotExist: return None def create_with_tags(self, name, price, tag_names): """创建产品并关联标签。""" product = self.create(name=name, price=price) tags = [Tag.objects.get_or_create(name=name)[0] for name in tag_names] product.tags.set(tags) return product def bulk_update_stock(self, product_ids, quantity): """批量更新多个产品的库存。""" return self.filter(id__in=product_ids).update(stock=quantity) # 在模型中 class Product(models.Model): # ... 字段 ... custom = ProductManager() ``` ## Django REST Framework 模式 ### 序列化器(Serializer)模式 ```python from rest_framework import serializers from django.contrib.auth.password_validation import validate_password from .models import Product, User class ProductSerializer(serializers.ModelSerializer): """Product 模型的序列化器。""" category_name = serializers.CharField(source='category.name', read_only=True) average_rating = serializers.FloatField(read_only=True) discount_price = serializers.SerializerMethodField() class Meta: model = Product fields = [ 'id', 'name', 'slug', 'description', 'price', 'discount_price', 'stock', 'category_name', 'average_rating', 'created_at' ] read_only_fields = ['id', 'slug', 'created_at'] def get_discount_price(self, obj): """如果适用,计算折扣价。""" if hasattr(obj, 'discount') and obj.discount: return obj.price * (1 - obj.discount.percent / 100) return obj.price def validate_price(self, value): """确保价格非负。""" if value < 0: raise serializers.ValidationError("价格不能为负数。") return value class ProductCreateSerializer(serializers.ModelSerializer): """用于创建产品的序列化器。""" class Meta: model = Product fields = ['name', 'description', 'price', 'stock', 'category'] def validate(self, data): """多字段的自定义校验。""" if data['price'] > 10000 and data['stock'] > 100: raise serializers.ValidationError( "高价值产品不能有大量库存。" ) return data class UserRegistrationSerializer(serializers.ModelSerializer): """用户注册序列化器。""" password = serializers.CharField( write_only=True, required=True, validators=[validate_password], style={'input_type': 'password'} ) password_confirm = serializers.CharField(write_only=True, style={'input_type': 'password'}) class Meta: model = User fields = ['email', 'username', 'password', 'password_confirm'] def validate(self, data): """校验两次输入的密码是否一致。""" if data['password'] != data['password_confirm']: raise serializers.ValidationError({ "password_confirm": "密码字段不匹配。" }) return data def create(self, validated_data): """创建并保存加密后的密码。""" validated_data.pop('password_confirm') password = validated_data.pop('password') user = User.objects.create(**validated_data) user.set_password(password) user.save() return user ``` ### 视图集(ViewSet)模式 ```python from rest_framework import viewsets, status, filters from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated, IsAdminUser from django_filters.rest_framework import DjangoFilterBackend from .models import Product from .serializers import ProductSerializer, ProductCreateSerializer from .permissions import IsOwnerOrReadOnly from .filters import ProductFilter from .filters import ProductFilter from .services import ProductService class ProductViewSet(viewsets.ModelViewSet): """Product 模型的视图集。""" queryset = Product.objects.select_related('category').prefetch_related('tags') permission_classes = [IsAuthenticated, IsOwnerOrReadOnly] filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter] filterset_class = ProductFilter search_fields = ['name', 'description'] ordering_fields = ['price', 'created_at', 'name'] ordering = ['-created_at'] def get_serializer_class(self): """根据操作(action)返回适当的序列化器类。""" if self.action == 'create': return ProductCreateSerializer return ProductSerializer def perform_create(self, serializer): """在保存时关联当前用户上下文。""" serializer.save(created_by=self.request.user) @action(detail=False, methods=['get']) def featured(self, request): """返回推荐产品。""" featured = self.queryset.filter(is_featured=True)[:10] serializer = self.get_serializer(featured, many=True) return Response(serializer.data) @action(detail=True, methods=['post']) def purchase(self, request, pk=None): """购买产品。"""
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen