用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/skeletorflet/opencode-kit --skill django-patterns命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Web accessibility (a11y). WCAG 2.1, ARIA, keyboard navigation, screen readers, testing tools.
Analytics and event tracking. Product analytics, Mixpanel, PostHog, Segment, GDPR compliance, event taxonomy.
UI animation patterns. CSS transitions, Framer Motion, GSAP, performance, accessibility.
基于 SOC 职业分类
正在显示 SKILL.md
| name | django-patterns |
| description | Django development principles and decision-making. Modern Django 4.2+ with DRF, Celery, Docker. |
Django development principles and decision-making. Learn to THINK, not copy-paste patterns.
This skill teaches decision-making principles for Django development.
myproject/
├── manage.py
├── myproject/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── app/
│ ├── __init__.py
│ ├── models.py
│ ├── views.py
│ ├── urls.py
│ └── admin.py
├── requirements.txt
└── .env
project/
├── manage.py
├── requirements.txt
├── .env
├── core/ # Project settings
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ ├── wsgi.py
│ └── asgi.py
├── apps/
│ ├── users/
│ │ ├── models.py
│ │ ├── views.py
│ │ ├── serializers.py
│ │ ├── urls.py
│ │ ├── permissions.py
│ │ └── apps.py
│ └── products/
├── services/ # Business logic
├── utils/ # Shared utilities
├── templates/
├── static/
└── media/
project/
├── core/
├── apps/
│ ├── users/
│ │ ├── __init__.py
│ │ ├── models/
│ │ │ ├── __init__.py
│ │ │ └── user.py
│ │ ├── repositories/
│ │ ├── services/
│ │ ├── views/
│ │ │ ├── __init__.py
│ │ │ ├── api/
│ │ │ └── admin/
│ │ ├── serializers/
│ │ ├── permissions/
│ │ └── tests/
│ └── orders/
├── domain/ # Domain layer
│ ├── entities/
│ ├── value_objects/
│ └── events/
├── application/ # Application services
│ ├── use_cases/
│ └── dtos/
├── infrastructure/ # DB, External APIs
│ ├── persistence/
│ ├── repositories/
│ └── external/
└── presentation/ # Views, APIs, Admin
# models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.utils import timezone
from django.conf import settings
class User(AbstractBaseUser, PermissionsMixin):
"""Custom user model."""
email = models.EmailField(unique=True)
username = models.CharField(max_length=150, unique=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
class Meta:
db_table = 'users'
ordering = ['-date_joined']
def __str__(self):
return self.email
class TimestampedModel(models.Model):
"""Abstract base with created/updated timestamps."""
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
ordering = ['-created_at']
class Product(TimestampedModel):
"""Product model with proper relationships."""
name = models.CharField(max_length=)
slug = models.SlugField(max_length=, unique=)
description = models.TextField(blank=)
price = models.DecimalField(max_digits=, decimal_places=)
stock = models.PositiveIntegerField(default=)
is_available = models.BooleanField(default=)
category = models.ForeignKey(
,
on_delete=models.SET_NULL,
null=,
related_name=
)
tags = models.ManyToManyField(, blank=)
owner = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name=
)
:
ordering = []
indexes = [
models.Index(fields=[]),
models.Index(fields=[]),
]
():
.name
class ProductManager(models.Manager):
"""Custom manager with query methods."""
def available(self):
return self.filter(is_available=True)
def in_stock(self):
return self.filter(stock__gt=0)
def by_category(self, category_slug):
return self.filter(category__slug=category_slug)
def with_price_range(self, min_price, max_price):
return self.filter(price__gte=min_price, price__lte=max_price)
class Product(models.Model):
# ... fields ...
objects = ProductManager()
# serializers.py
from rest_framework import serializers
from .models import User, Product
from django.contrib.auth.password_validation import validate_password
class UserSerializer(serializers.ModelSerializer):
"""Serializer for User model."""
class Meta:
model = User
fields = ['id', 'email', 'username', 'date_joined']
read_only_fields = ['id', 'date_joined']
class UserCreateSerializer(serializers.ModelSerializer):
"""Serializer for creating users."""
password = serializers.CharField(write_only=True)
password_confirm = serializers.CharField(write_only=True)
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': 'Passwords do not match'})
validate_password(data['password'])
return data
def create(self, validated_data):
validated_data.pop('password_confirm')
user = User.objects.create_user(**validated_data)
user
(serializers.ModelSerializer):
category_name = serializers.CharField(source=, read_only=)
owner_email = serializers.CharField(source=, read_only=)
:
model = Product
fields = [
, , , , ,
, , , ,
, , ,
]
read_only_fields = [, , ]
():
data = ().to_representation(instance)
data[] = (instance.price)
data
# views.py
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from django.db.models import Q
from .models import Product
from .serializers import ProductSerializer
class ProductViewSet(viewsets.ModelViewSet):
"""ViewSet for Product with custom actions."""
queryset = Product.objects.select_related('category', 'owner').all()
serializer_class = ProductSerializer
lookup_field = 'slug'
# Filtering
filterset_fields = ['category', 'is_available']
search_fields = ['name', 'description']
ordering_fields = ['price', 'created_at']
ordering = ['-created_at']
def get_permissions(self):
if self.action in ['list', 'retrieve']:
return []
elif self.action in ['create']:
return [IsAuthenticated()]
elif self.action [, , ]:
[IsAuthenticated(), IsAdminUser()]
[IsAuthenticated()]
():
queryset = ().get_queryset()
in_stock = .request.query_params.get()
in_stock:
queryset = queryset.(stock__gt=)
queryset
():
cheap_products = .queryset.(price__lt=)
serializer = .get_serializer(cheap_products, many=)
Response(serializer.data)
():
product = .get_object()
product.is_available =
product.save()
Response({: })
# urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ProductViewSet
router = DefaultRouter()
router.register(r'products', ProductViewSet, basename='product')
urlpatterns = [
path('', include(router.urls)),
]
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
# settings.py - Simple JWT
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
'AUTH_HEADER_TYPES': ('Bearer',),
}
# permissions.py
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
"""Custom permission: only owners can edit."""
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
return obj.owner == request.user or request.user.is_staff
class IsAdminOrReadOnly(permissions.BasePermission):
"""Only admins can write, everyone can read."""
def has_permission(self, request, view):
if request.method in permissions.SAFE_METHODS:
return True
return request.user and request.user.is_staff
# tasks.py
from celery import shared_task
from django.core.mail import send_mail
@shared_task
def send_order_confirmation(order_id):
"""Send order confirmation email."""
order = Order.objects.get(id=order_id)
send_mail(
'Order Confirmation',
f'Your order #{order_id} has been confirmed.',
'noreply@example.com',
[order.user.email],
fail_silently=False,
)
@shared_task
def process_order(order_id):
"""Process order asynchronously."""
from .services import OrderProcessor
processor = OrderProcessor(order_id)
processor.process()
return f'Order {order_id} processed'
# Celery configuration
# celery.py
from celery import Celery
app = Celery('project')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
app.conf.beat_schedule = {
'delete-expired-orders': {
'task': 'orders.tasks.delete_expired_orders',
'schedule': 86400, # Daily
},
}
# tests/test_models.py
from django.test import TestCase
from django.contrib.auth import get_user_model
from products.models import Product, Category
User = get_user_model()
class UserModelTest(TestCase):
"""Test User model."""
def test_create_user(self):
user = User.objects.create_user(
username='testuser',
email='test@example.com',
password='testpass123'
)
self.assertEqual(user.email, 'test@example.com')
self.assertFalse(user.is_staff)
self.assertFalse(user.is_superuser)
def test_create_superuser(self):
user = User.objects.create_superuser(
email='admin@example.com',
password='adminpass123'
)
self.assertTrue(user.is_staff)
self.assertTrue(user.is_superuser)
class ProductModelTest(TestCase):
def test_product_creation(self):
category = Category.objects.create(name='Electronics')
product = Product.objects.create(
name='Laptop',
slug='laptop',
price=999.99,
category=category
)
self.assertEqual(str(product), )
.assertEqual(product.category, category)
# settings.py - Key configurations
import os
from pathlib import Path
from dotenv import load_dotenv
load_dotenv()
BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = os.getenv('SECRET_KEY', 'django-insecure-dev-key')
DEBUG = os.getenv('DEBUG', 'False') == 'True'
ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', 'localhost,127.0.0.1').split(',')
# Database
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('POSTGRES_DB', 'mydb'),
'USER': os.getenv('POSTGRES_USER', 'postgres'),
'PASSWORD': os.getenv('POSTGRES_PASSWORD', 'password'),
'HOST': os.getenv('POSTGRES_HOST', 'localhost'),
'PORT': os.getenv('POSTGRES_PORT', '5432'),
}
}
# Caching (use Redis in production)
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
}
}
# Redis for Celery in production:
# CACHES = {
# 'default': {
# 'BACKEND': 'django.core.cache.backends.redis.RedisCache',
# 'LOCATION': os.getenv('REDIS_URL'),
# }
# }
REST_FRAMEWORK = {
: ,
: ,
: [
,
,
],
}
LOGGING = {
: ,
: ,
: {
: {
: ,
},
: {
: ,
: ,
},
},
: {
: [, ],
: ,
},
}
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy project
COPY . .
# Expose port
EXPOSE 8000
# Run
CMD ["gunicorn", "core.wsgi:application", "--bind", "0.0.0.0:8000"]
# docker-compose.yml
services:
web:
build: .
ports:
- "8000:8000"
environment:
- DEBUG=False
- DATABASE_URL=postgresql://postgres:password@db:5432/mydb
depends_on:
- db
- redis
db:
image: postgres:15-alpine
environment:
POSTGRES_DB: mydb
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
celery:
build: .
command: celery -A core worker -l info
depends_on:
- redis
volumes:
postgres_data:
Before implementing:
Remember: Django has "batteries included". Use built-in features: Admin, Forms, Auth, Sessions, Messages. Think in Django.