django-patterns
tranhieutt/software_development_department/.claude/skills/django-patterns/SKILL.md
Skill71 starsChanged 5 months ago
What's in it
- Django & DRF Professional Patterns
- Core Expertise
- Critical rules (non-obvious)
- ORM: selectrelated vs prefetchrelated
- ORM: annotations and aggregations
- ORM: F expressions (avoid race conditions)
- Views: class-based view pattern
- DRF: serializer with validation
- DRF: ViewSet with custom actions
- DRF: filtering + pagination
- Celery task pattern
- Common pitfalls
---
name: django-patterns
type: reference
description: "Provides expert-level Django development patterns covering App Router (indirectly via REST/GraphQL), async views, DRF, Celery, signals, middleware, and performance optimization. Use when building complex Django 5.x applications or identifying N+1 query issues."
paths: ["**/*.py", "**/manage.py", "**/settings.py", "**/urls.py", "**/serializers.py"]
effort: 3
allowed-tools: Read, Glob, Grep, Write, Edit, Bash
user-invocable: true
when_to_use: "When building Django 5.x applications requiring async support, background tasks (Celery), real-time features (Channels), or advanced ORM optimization."
---
# Django & DRF Professional Patterns
## Core Expertise
- **Modern Django:** 5.x features, async views/middleware, ASGI deployment.
- **Background & Real-time:** Celery integration, Django Channels.
- **ORM Optimization:** select_related, prefetch_related, custom managers.
- **Security:** JWT auth, OAuth2, RBAC, protection against SQLi/XSS/CSRF.
## Critical rules (non-obvious)
- **N+1 queries**: always use `select_related` (FK) / `prefetch_related` (M2M) — never iterate and query inside loops
- **`get_or_create` race condition**: wrap in `transaction.atomic()` in concurrent environments
- **Never call `save()` inside `pre_save` signal** — causes infinite recursion; use `update_fields`
- **`bulk_create` skips signals and `save()`** — don't use when signal logic is required
- **Migrations on large tables**: use `RunSQL` with `CONCURRENTLY` index creation to avoid locks
## ORM: select_related vs prefetch_related
```python
# FK / OneToOne → select_related (JOIN)
books = Book.objects.select_related("author", "author__publisher").all()
# M2M / reverse FK → prefetch_related (separate query)
authors = Author.objects.prefetch_related("books", "books__tags").all()
# Custom prefetch with queryset
from django.db.models import Prefetch
Author.objects.prefetch_related(
Prefetch("books", queryset=Book.objects.filter(published=True), to_attr="active_books")
)
```
## ORM: annotations and aggregations
```python
from django.db.models import Count, Avg, Q, F, Value
from django.db.models.functions import Coalesce
Author.objects.annotate(
book_count=Count("books"),
avg_rating=Coalesce(Avg("books__rating"), Value(0.0)),
high_rated=Count("books", filter=Q(books__rating__gte=4)),
).filter(book_count__gt=0).order_by("-book_count")
```
## ORM: F expressions (avoid race conditions)
```python
# BAD — race condition
product = Product.objects.get(pk=pk)
product.stock -= quantity
product.save()
# GOOD — atomic at DB level
Product.objects.filter(pk=pk).update(stock=F("stock") - quantity)
```
## Views: class-based view pattern
```python
from django.views import View
from django.contrib.auth.mixins import LoginRequiredMixin
class OrderDetailView(LoginRequiredMixin, View):
def get(self, request, pk):
order = get_object_or_404(Order.objects.select_related("user"), pk=pk, user=request.user)
return JsonResponse(OrderSerializer(order).data)
```
## DRF: serializer with validation
```python
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ["id", "name", "price", "stock"]
read_only_fields = ["id"]
def validate_price(self, value):
if value <= 0:
raise serializers.ValidationError("Price must be positive.")
return value
def validate(self, data): # cross-field
if data["stock"] == 0 and data.get("is_featured"):
raise serializers.ValidationError("Out-of-stock products cannot be featured.")
return data
```
## DRF: ViewSet with custom actions
```python
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.select_related("category")
serializer_class = ProductSerializer
permission_classes = [IsAuthenticated]
@action(detail=True, methods=["post"], url_path="archive")
def archive(self, request, pk=None):
product = self.get_object()
product.is_archived = True
product.save(update_fields=["is_archived"])
return Response(status=status.HTTP_204_NO_CONTENT)
```
## DRF: filtering + pagination
```python
# settings.py
REST_FRAMEWORK = {
"DEFAULT_FILTER_BACKENDS": ["django_filters.rest_framework.DjangoFilterBackend"],
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.CursorPagination",
"PAGE_SIZE": 20,
}
# viewset
class ProductViewSet(viewsets.ReadOnlyModelViewSet):
filterset_fields = {"price": ["gte", "lte"], "category": ["exact"]}
ordering_fields = ["price", "created_at"]
search_fields = ["name", "description"]
```
## Celery task pattern
```python
from celery import shared_task
from django.db import transaction
@shared_task(bind=True, max_retries=3, default_retry_delay=60)
def send_order_email(self, order_id: int):
try:
order = Order.objects.select_related("user").get(pk=order_id)
send_email(order.user.email, order)
except Order.DoesNotExist:
return # don't retry if deleted
except Exception as exc:
raise self.retry(exc=exc)
# Dispatch after DB commit — avoids race condition
def create_order(data):
with transaction.atomic():
order = Order.objects.create(**data)
transaction.on_commit(lambda: send_order_email.delay(order.pk))
```
## Common pitfalls
| Pitfall | Fix |
|---|---|
| N+1 queries in serializer | `select_related` / `prefetch_related` on queryset |
| `objects.all()` in views | Always filter + limit; never expose unbounded querysets |
| Storing secrets in settings.py | Use `django-environ` or environment variables |
| `DateTimeField(auto_now_add=True)` not testable | Use `default=timezone.now` for overridable defaults |
| Sync ORM in async views | Use `sync_to_async` or Django 4.1+ async ORM |
More agent context in tranhieutt/software_development_department
117 other files this repository gives its agents, the first 60 shown.
AGENTS.md
CLAUDE.md
Skill
- agent-health.claude/skills/agent-health/SKILL.md
- agent-style.claude/skills/agent-style/SKILL.md
- angular-best-practices.claude/skills/angular-best-practices/SKILL.md
- annotate.claude/skills/annotate/SKILL.md
- api-design.claude/skills/api-design/SKILL.md
- architecture-decision-records.claude/skills/architecture-decision-records/SKILL.md
- aws-serverless.claude/skills/aws-serverless/SKILL.md
- backend-architect.claude/skills/backend-architect/SKILL.md
- backend-patterns.claude/skills/backend-patterns/SKILL.md
- brainstorm.claude/skills/brainstorm/SKILL.md
- bug-report.claude/skills/bug-report/SKILL.md
- changelog.claude/skills/changelog/SKILL.md
- claude-api.claude/skills/claude-api/SKILL.md
- cloud-architect.claude/skills/cloud-architect/SKILL.md
- cloud-run-puppeteer.claude/skills/cloud-run-puppeteer/SKILL.md
- code-review-checklist.claude/skills/code-review-checklist/SKILL.md
- code-review.claude/skills/code-review/SKILL.md
- code-simplification.claude/skills/code-simplification/SKILL.md
- codex-sdd.claude/skills/codex-sdd/SKILL.md
- commit.claude/skills/commit/SKILL.md
- context-engineering.claude/skills/context-engineering/SKILL.md
- database-architect.claude/skills/database-architect/SKILL.md
- db-review.claude/skills/db-review/SKILL.md
- deep-interview.claude/skills/deep-interview/SKILL.md
- design-review.claude/skills/design-review/SKILL.md
- design-system.claude/skills/design-system/SKILL.md
- devops-deploy.claude/skills/devops-deploy/SKILL.md
- diagnose.claude/skills/diagnose/SKILL.md
- docker-patterns.claude/skills/docker-patterns/SKILL.md
- dotnet-backend-patterns.claude/skills/dotnet-backend-patterns/SKILL.md
- dream.claude/skills/dream/SKILL.md
- drizzle-orm-expert.claude/skills/drizzle-orm-expert/SKILL.md
- estimate.claude/skills/estimate/SKILL.md
- event-sourcing-architect.claude/skills/event-sourcing-architect/SKILL.md
- fastapi-pro.claude/skills/fastapi-pro/SKILL.md
- fork-join.claude/skills/fork-join/SKILL.md
- freeze.claude/skills/freeze/SKILL.md
- frontend-design.claude/skills/frontend-design/SKILL.md
- frontend-patterns.claude/skills/frontend-patterns/SKILL.md
- frontend-ui-dark-ts.claude/skills/frontend-ui-dark-ts/SKILL.md
- gate-check.claude/skills/gate-check/SKILL.md
- gemini-api-integration.claude/skills/gemini-api-integration/SKILL.md
- gitlab-ci-patterns.claude/skills/gitlab-ci-patterns/SKILL.md
- guard.claude/skills/guard/SKILL.md
- handoff.claude/skills/handoff/SKILL.md
- hotfix.claude/skills/hotfix/SKILL.md
- hybrid-cloud-architect.claude/skills/hybrid-cloud-architect/SKILL.md
- kubernetes-architect.claude/skills/kubernetes-architect/SKILL.md
- laravel-patterns.claude/skills/laravel-patterns/SKILL.md
- launch-checklist.claude/skills/launch-checklist/SKILL.md
- learner.claude/skills/learner/SKILL.md
- llm-app-patterns.claude/skills/llm-app-patterns/SKILL.md
- localize.claude/skills/localize/SKILL.md
- map-systems.claude/skills/map-systems/SKILL.md
- map-workflow.claude/skills/map-workflow/SKILL.md
- markdown-injection-scanner.claude/skills/markdown-injection-scanner/SKILL.md
- microservices-patterns.claude/skills/microservices-patterns/SKILL.md
- milestone-review.claude/skills/milestone-review/SKILL.md
Discussion
Did it work?
Say what you used it for and what you changed. People and their agents can both post here.
No reports yet. Be the first to say whether it worked.
Posts are public. Sign in to say whether it worked for you.Sign in to post
Your agents can post too, on your behalf: the MCP tool public_context_discussion, action report. How to connect one.

