一键导入
tpl-backend-django-drf-celery
Template do pack (backend/03-django-drf-celery.md). Orienta o agente em APIs, servicos e arquitetura backend alinhado a esse contexto.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Template do pack (backend/03-django-drf-celery.md). Orienta o agente em APIs, servicos e arquitetura backend alinhado a esse contexto.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | tpl-backend-django-drf-celery |
| description | Template do pack (backend/03-django-drf-celery.md). Orienta o agente em APIs, servicos e arquitetura backend alinhado a esse contexto. |
| metadata | {"version":"1.0.0","source_template":"backend/03-django-drf-celery.md","generated_by":"install_pack_templates_as_claude_skills"} |
Skill gerado a partir do pack templates-claude-code. Arquivo de origem: backend/03-django-drf-celery.md. Use como baseline e adapte ao projeto antes de mudancas grandes.
| Technology | Version | Purpose |
|---|---|---|
| Python | 3.12 | Runtime |
| Django | 5.0 | Web framework |
| Django REST Framework | 3.15+ | REST API toolkit |
| PostgreSQL | 16 | Primary database |
| psycopg | 3.x | Async-capable PG driver |
| Celery | 5.4+ | Async task queue |
| Redis | 7.x | Celery broker + cache + result backend |
| djangorestframework-simplejwt | 5.x | JWT authentication |
| django-filter | 24.x | QuerySet filtering for ViewSets |
| pytest-django | 4.8+ | Django test integration |
| factory_boy | 3.x | Test fixtures |
| Black | 24.x | Code formatter |
| Ruff | 0.4+ | Linter |
config/
├── settings/
│ ├── base.py # Shared settings
│ ├── development.py # Dev overrides
│ ├── production.py # Prod overrides (env-driven)
│ └── test.py # Test overrides (SQLite or test PG)
├── urls.py # Root URL conf
└── celery.py # Celery app instance
apps/
└── users/
├── migrations/ # Auto-generated
├── models.py # Django ORM models
├── serializers.py # DRF serializers
├── views.py # ViewSets
├── urls.py # Router registration
├── permissions.py # Custom DRF permissions
├── tasks.py # Celery tasks
├── services.py # Business logic
├── filters.py # django-filter FilterSets
└── tests/
├── test_views.py
├── test_serializers.py
├── test_tasks.py
└── factories.py # factory_boy factories
manage.py
requirements/
├── base.txt
├── dev.txt
└── prod.txt
services.py — not in ViewSets or serializersvalidate_* methods only validate format/consistency — no DB queries in validateservices.py or manager methods — not scattered in viewsmanage.py commands import and call service functions directly__str__ and class Meta with verbose_name and ordering# apps/users/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 .serializers import UserSerializer, UserCreateSerializer, PasswordChangeSerializer
from .services import UserService
class UserViewSet(viewsets.ModelViewSet):
serializer_class = UserSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
if self.request.user.is_staff:
return UserService.list_all()
return UserService.list_active()
def get_permissions(self):
if self.action in ['destroy', 'list']:
return [IsAdminUser()]
return super().get_permissions()
def get_serializer_class(self):
if self.action == 'create':
return UserCreateSerializer
return self.serializer_class
def perform_create(self, serializer):
user = UserService.create_user(**serializer.validated_data)
serializer.instance = user # update serializer with saved instance
@action(detail=False, methods=['get', 'patch'], url_path='me')
def me(self, request):
if request.method == 'GET':
return Response(UserSerializer(request.user).data)
serializer = UserSerializer(request.user, data=request.data, partial=True)
serializer.is_valid(raise_exception=True)
UserService.update_user(request.user, **serializer.validated_data)
return Response(serializer.data)
@action(detail=False, methods=['post'], url_path='change-password')
def change_password(self, request):
serializer = PasswordChangeSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
UserService.change_password(request.user, **serializer.validated_data)
return Response(status=status.HTTP_204_NO_CONTENT)
# apps/users/serializers.py
from rest_framework import serializers
from django.contrib.auth.password_validation import validate_password
from .models import User
class UserCreateSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True, validators=[validate_password])
password_confirm = serializers.CharField(write_only=True)
class Meta:
model = User
fields = ['email', 'name', 'password', 'password_confirm']
def validate(self, data):
if data['password'] != data.pop('password_confirm'):
raise serializers.ValidationError({'password_confirm': 'Passwords do not match.'})
return data
# apps/users/permissions.py
from rest_framework.permissions import BasePermission
class IsOwnerOrAdmin(BasePermission):
def has_object_permission(self, request, view, obj):
return obj == request.user or request.user.is_staff
Always use bind=True for access to self (retry + task ID). Always define max_retries, default_retry_delay. Tasks must be idempotent — running twice should have the same outcome as running once.
# apps/users/tasks.py
from celery import shared_task
from celery.utils.log import get_task_logger
from .services import UserService
logger = get_task_logger(__name__)
@shared_task(
bind=True,
max_retries=3,
default_retry_delay=60, # seconds
serializer='json', # NEVER use pickle
acks_late=True, # ack only after task completes
reject_on_worker_lost=True, # re-queue if worker dies mid-task
name='users.send_welcome_email',
)
def send_welcome_email(self, user_id: int) -> str:
"""Send welcome email to new user. Idempotent: safe to retry."""
try:
result = UserService.send_welcome_email(user_id=user_id)
logger.info("Welcome email sent", extra={"user_id": user_id})
return result
except UserService.EmailAlreadySentError:
logger.warning("Email already sent (idempotency check)", extra={"user_id": user_id})
return "already_sent"
except Exception as exc:
logger.error("Failed to send email", exc_info=True, extra={"user_id": user_id})
raise self.retry(exc=exc)
Celery Rules:
serializer='json' — never pickle (security risk)acks_late=True on tasks that touch external servicesuser_id: int, not Django model instances (not serializable cleanly)extra={} — structured logging, never f-string sensitive dataself.retry(exc=exc, countdown=2 ** self.request.retries * 60)| Trigger | Method | Route | Auth | ViewSet Action |
|---|---|---|---|---|
| Register | POST | /api/v1/users/ | Public | UserViewSet.create |
| Login | POST | /api/v1/auth/login/ | Public | TokenObtainPairView |
| Refresh token | POST | /api/v1/auth/refresh/ | Refresh token | TokenRefreshView |
| List users | GET | /api/v1/users/ | Admin | UserViewSet.list |
| Get user | GET | /api/v1/users/{id}/ | Admin | UserViewSet.retrieve |
| Get my profile | GET | /api/v1/users/me/ | Bearer | UserViewSet.me (GET) |
| Update my profile | PATCH | /api/v1/users/me/ | Bearer | UserViewSet.me (PATCH) |
| Change password | POST | /api/v1/users/change-password/ | Bearer | UserViewSet.change_password |
| Delete user | DELETE | /api/v1/users/{id}/ | Admin | UserViewSet.destroy |
Before opening a PR, verify ALL of the following:
ruff check . && black --check . passes with zero issuespytest --tb=short -x passes with zero failurespython manage.py migrate --check — no unapplied migrationsCELERY_TASK_ALWAYS_EAGER = TrueQuerySet usage inside ViewSets — goes through servicesserializer.is_valid(raise_exception=True) used (not manual 400 handling)select_related / prefetch_related used where N+1 queries are possiblepassword, token) marked write_only=True in serializersCELERY_TASK_ROUTES (dedicated queues in prod)pickle as Celery serializer — always jsonapply_async call site — batch IDsexcept Exception: pass in tasks — always log or re-raisecreate() or update() — use servicesUser.objects.filter(...) directly in ViewSets — go through servicesCELERY_ALWAYS_EAGER=True in productionDEBUG=True or hardcoded secretsGenerate custom favicons from logos, text, or brand colours. Produces favicon.svg, favicon.ico, apple-touch-icon.png, icon-192/512.png, and web manifest. Use whenever the user wants a favicon, mentions replacing a CMS default favicon, converting a logo into a favicon, creating branded initials icons, or troubleshooting favicon not displaying / iOS black square / missing manifest.
"Get a second opinion from leading AI models on code, architecture, strategy, prompting, or anything. Queries models via OpenRouter, Gemini, or OpenAI APIs. Supports single opinion, multi-model consensus, and devil's advocate patterns. Use whenever the user says 'brains trust', 'second opinion', 'ask gemini', 'ask gpt', 'peer review', 'consult another model', 'challenge this', or 'devil's advocate'."
Run an independent code review using the OpenAI Codex CLI in headless mode. Gets a second opinion from a different model family (GPT-5/o3) on recent changes, a PR, a commit, or the whole app — covering bugs, regressions, security, data consistency, UX/state bugs, performance risks, and testing gaps. Saves a severity-prioritised report to .jez/reviews/. Triggers: 'codex review', 'review with codex', 'second opinion on this code', 'independent code review', 'what does codex think', 'get codex to review'.
Deep research and discovery before building something new. Explores local projects for reusable code, researches competitors, reads forums and reviews, analyses plugin ecosystems, investigates technical options, and produces a comprehensive research brief. Three depths: focused (30 min), wide (1-2 hours), deep (3-6 hours). Triggers: 'research this', 'deep research', 'discovery', 'explore the space', 'what should I build', 'competitive analysis', 'before I start building', 'research before coding'.
Plan and execute entire application builds. Generates phased delivery roadmaps, then executes them autonomously — phase by phase, committing at milestones, deploying, testing, and continuing until done or stuck. Modes: plan (generate roadmap), start (begin executing), resume (continue from where you left off), status (show progress). Triggers: 'roadmap', 'plan the build', 'start building', 'resume the build', 'keep going', 'build the whole thing', 'execute the roadmap', 'what phase are we on'.
Walk through a live web app AS a real user to find usability + behavioural bugs that static reviews miss. REQUIRES proof of interaction (typing, clicking, sending, observing) before any verdict — a sweep that didn't interact terminates with verdict 'Incomplete'. Walks threads, exercises every element, runs the multi-pane stress matrix, visual polish sweep, component perfection checklist, automated a11y (axe-core), pragmatic performance budget (LCP/CLS/INP), scenario battery (11 scenarios), and stress recipes including the real-flavour data battery. Hard gates: console errors/warnings = 0, network 5xx = 0, layout collapse = 0, axe Critical/Serious = 0, perf budget green. Audit-the-audit meta-check rejects rushed reports. Each finding has reproduction steps, evidence path, and suspected code location. Trigger with 'ux audit', 'walkthrough', 'qa sweep', 'audit the app', 'dogfood this', 'check all pages', 'find what's broken', 'stress the UI'.