Agent skill
django
Django 5+ framework guardrails, patterns, and best practices for AI-assisted development. Use when working with Django projects, or when the user mentions Django. Provides ORM patterns, views, templates, DRF, admin, and security guidelines.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/django
Metadata
Additional technical details for this skill
- author
- samuel
- version
- 1.0
- category
- framework
- language
- python
- extensions
- .py
SKILL.md
Django Framework Guide
Applies to: Django 5+, Django REST Framework, Django Channels Language: Python 3.10+
Core Principles
- Batteries Included: Leverage Django's built-in features before adding third-party packages
- DRY: Don't Repeat Yourself -- use abstract models, mixins, and shared utilities
- Fat Models, Thin Views: Keep business logic in models and services, not views
- Explicit Over Implicit: Use clear URL patterns, explicit imports, named relationships
- Security by Default: CSRF, XSS protection, SQL injection prevention are built in
When to Use Django
Good fit:
- Full-stack web applications with templates
- Admin interface needed out of the box
- Content management systems
- Session-based authentication
- ORM with built-in migrations
Consider alternatives:
- Pure APIs with async-first needs (FastAPI)
- Minimal framework overhead (Flask)
- Real-time heavy workloads without Channels
Project Structure
myproject/
├── manage.py
├── pyproject.toml
├── requirements/
│ ├── base.txt
│ ├── dev.txt
│ └── prod.txt
├── config/ # Project configuration
│ ├── __init__.py
│ ├── settings/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── dev.py
│ │ └── prod.py
│ ├── urls.py
│ ├── wsgi.py
│ └── asgi.py
├── apps/ # Django applications
│ ├── users/
│ │ ├── __init__.py
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── models.py
│ │ ├── views.py
│ │ ├── urls.py
│ │ ├── forms.py
│ │ ├── serializers.py # If using DRF
│ │ ├── services.py # Business logic
│ │ └── tests/
│ │ ├── __init__.py
│ │ ├── test_models.py
│ │ ├── test_views.py
│ │ └── test_services.py
│ └── core/ # Shared utilities
│ ├── __init__.py
│ ├── models.py # Abstract base models
│ └── mixins.py
├── templates/
│ ├── base.html
│ └── components/
├── static/
│ ├── css/
│ └── js/
└── tests/
└── conftest.py
- Split settings into
base.py,dev.py,prod.py - Group apps under
apps/directory - Keep
core/app for shared abstract models and utilities - Place business logic in
services.py, not in views - Co-locate tests inside each app under
tests/directory
Guardrails
Settings
- Never hardcode
SECRET_KEY-- usepython-decoupleor environment variables - Split settings:
base.py(shared),dev.py(debug),prod.py(secure) - Always define
AUTH_USER_MODELbefore first migration - Set
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" - Use
ALLOWED_HOSTSin production (never["*"])
Models
- Always define
__str__on every model - Always set
class Metawithdb_table,ordering, andindexes - Use abstract base models for shared fields (
TimeStampedModel,UUIDModel) - Use
TextChoices/IntegerChoicesfor status fields (not raw strings) - Add
related_nameto all ForeignKey and OneToOneField relationships - Use
on_deleteexplicitly:CASCADE,PROTECT,SET_NULL,SET_DEFAULT - Add database indexes for frequently queried fields
- Use
validatorsat model level for domain constraints
Abstract Base Models
# apps/core/models.py
from django.db import models
import uuid
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
class UUIDModel(models.Model):
"""Abstract base with UUID primary key."""
id = models.UUIDField(
primary_key=True, default=uuid.uuid4, editable=False
)
class Meta:
abstract = True
Custom User Model
- Always create a custom user model before the first migration
- Extend
AbstractUser(notAbstractBaseUserunless you need full control) - Set
AUTH_USER_MODEL = "users.User"in settings
# apps/users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
from apps.core.models import TimeStampedModel, UUIDModel
class User(AbstractUser, UUIDModel, TimeStampedModel):
email = models.EmailField(unique=True)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username"]
class Meta:
db_table = "users"
ordering = ["-created_at"]
indexes = [models.Index(fields=["email"])]
def __str__(self) -> str:
return self.email
Views and URLs
Class-Based Views (CBVs)
- Use
ListView,DetailView,CreateView,UpdateViewfor CRUD - Use
LoginRequiredMixinfor authenticated views - Override
get_queryset()to add filtering andselect_related/prefetch_related - Override
form_valid()to inject the current user
from django.views.generic import ListView
from django.db.models import Q
from .models import Product
class ProductListView(ListView):
model = Product
template_name = "products/list.html"
context_object_name = "products"
paginate_by = 20
def get_queryset(self):
qs = Product.objects.filter(
status=Product.Status.PUBLISHED
)
search = self.request.GET.get("q")
if search:
qs = qs.filter(
Q(name__icontains=search)
| Q(description__icontains=search)
)
return qs.select_related("category")
URL Configuration
# config/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path("api/", include("apps.api.urls")),
path("", include("apps.products.urls")),
]
- Use
include()for app-level URL namespaces - Use
app_namein each app'surls.pyfor reverse resolution - Serve media files in DEBUG mode only
ORM Essentials
Query Optimization
- Always use
select_related()for ForeignKey/OneToOne (SQL JOIN) - Always use
prefetch_related()for ManyToMany/reverse FK (separate query) - Use
only()ordefer()to limit fields when not all columns needed - Never call
Model.objects.all()without pagination or limits - Use
F()expressions for database-level operations - Use
Q()objects for complex lookups
Avoiding N+1 Queries
# BAD: N+1 queries
for product in Product.objects.all():
print(product.category.name) # Extra query per product
# GOOD: Single JOIN query
for product in Product.objects.select_related("category"):
print(product.category.name) # No extra queries
Transactions
- Use
@transaction.atomicfor multi-step writes - Use
select_for_update()for optimistic locking
from django.db import transaction
@transaction.atomic
def transfer_stock(source_id, dest_id, qty):
source = Product.objects.select_for_update().get(id=source_id)
dest = Product.objects.select_for_update().get(id=dest_id)
source.stock -= qty
dest.stock += qty
source.save(update_fields=["stock"])
dest.save(update_fields=["stock"])
Admin Configuration
from django.contrib import admin
from .models import Product
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ["name", "category", "price", "status"]
list_filter = ["status", "category", "created_at"]
search_fields = ["name", "description"]
prepopulated_fields = {"slug": ("name",)}
readonly_fields = ["created_at", "updated_at"]
ordering = ["-created_at"]
fieldsets = (
(None, {"fields": ("name", "slug", "description")}),
("Pricing", {"fields": ("price", "stock")}),
("Classification", {"fields": ("category", "status")}),
("Timestamps", {
"fields": ("created_at", "updated_at"),
"classes": ("collapse",),
}),
)
- Always register models with
@admin.register(Model) - Use
list_displayfor useful columns,list_filterfor filtering - Use
prepopulated_fieldsfor slug generation - Group fields with
fieldsetsfor organized admin forms
Django REST Framework (DRF)
Settings
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework.authentication.SessionAuthentication",
"rest_framework_simplejwt.authentication.JWTAuthentication",
],
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework.permissions.IsAuthenticated",
],
"DEFAULT_PAGINATION_CLASS": (
"rest_framework.pagination.PageNumberPagination"
),
"PAGE_SIZE": 20,
"DEFAULT_THROTTLE_RATES": {
"anon": "100/hour",
"user": "1000/hour",
},
}
ViewSets and Routers
- Use
ModelViewSetfor full CRUD - Use
@action(detail=True/False)for custom endpoints - Override
get_serializer_class()for different read/write serializers - Override
get_queryset()to addselect_related/prefetch_related
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.select_related("category")
permission_classes = [IsAuthenticatedOrReadOnly]
def get_serializer_class(self):
if self.action in ["create", "update", "partial_update"]:
return ProductCreateSerializer
return ProductSerializer
def perform_create(self, serializer):
serializer.save(created_by=self.request.user)
@action(detail=True, methods=["post"])
def publish(self, request, pk=None):
product = self.get_object()
product.status = Product.Status.PUBLISHED
product.save(update_fields=["status"])
return Response({"status": "published"})
Serializers
- Use
ModelSerializerfor standard CRUD - Add
read_only_fieldsfor computed/auto fields - Validate in
validate_<field>()orvalidate()methods - Use nested serializers for read, flat IDs for write
Security Essentials
- CSRF: Enabled by default for forms; use
@csrf_exemptsparingly - XSS: Django templates auto-escape by default; never use
|safewith user data - SQL Injection: ORM uses parameterized queries; never use raw SQL with string formatting
- Clickjacking:
X-Frame-Optionsmiddleware enabled by default - HTTPS: Set
SECURE_SSL_REDIRECT = Truein production - HSTS: Set
SECURE_HSTS_SECONDSin production - Cookies: Set
SESSION_COOKIE_SECURE = TrueandCSRF_COOKIE_SECURE = True - Passwords: Use
AUTH_PASSWORD_VALIDATORS(enabled by default) - CORS: Use
django-cors-headerswith explicit allowed origins (neverCORS_ALLOW_ALL_ORIGINSin production)
Testing
Standards
- Use
pytestwithpytest-django(not Django's built-in test runner) - Mark database tests with
@pytest.mark.django_db - Use
factory-boyor fixtures for test data - Use
APIClientfor DRF endpoint testing - Coverage target: >80% for business logic
- Test file naming:
test_models.py,test_views.py,test_services.py
Fixtures
# conftest.py
import pytest
from rest_framework.test import APIClient
from apps.users.models import User
@pytest.fixture
def api_client():
return APIClient()
@pytest.fixture
def user(db):
return User.objects.create_user(
username="testuser",
email="[email protected]",
password="testpass123",
)
@pytest.fixture
def authenticated_client(api_client, user):
api_client.force_authenticate(user=user)
return api_client
Commands Reference
# Development
python manage.py runserver
python manage.py shell_plus # django-extensions
# Migrations
python manage.py makemigrations
python manage.py migrate
python manage.py showmigrations
# Testing
pytest
pytest -v --cov=apps --cov-report=html
pytest apps/products/ -k "test_create"
# Database
python manage.py dbshell
python manage.py dumpdata products > fixtures/products.json
python manage.py loaddata fixtures/products.json
# Static files
python manage.py collectstatic
# Celery
celery -A config worker -l info
celery -A config beat -l info
Dependencies
Base: Django>=5.0, djangorestframework, django-cors-headers, django-filter, djangorestframework-simplejwt, python-decouple, psycopg2-binary, whitenoise
Dev: pytest, pytest-django, pytest-cov, factory-boy, django-debug-toolbar, django-extensions, black, ruff, mypy, django-stubs
Best Practices
Do
- Use
select_relatedandprefetch_relatedfor every queryset - Create indexes for frequently queried fields
- Use
@transaction.atomicfor multi-step operations - Validate at both model level and serializer level
- Write services for business logic (not in views)
- Use signals sparingly (prefer explicit service calls)
- Cache expensive queries with Django cache framework
- Use environment variables for all configuration
Don't
- Put business logic in views
- Use raw SQL without parameterization
- Ignore N+1 query problems
- Store sensitive data in settings files
- Use
Model.objects.all()without limits - Skip migrations in production
- Use
CORS_ALLOW_ALL_ORIGINS = Truein production - Use
|safetemplate filter with user-provided data
Advanced Topics
For detailed code examples and advanced patterns, see:
- references/patterns.md -- DRF serializers, middleware, services, signals, Celery tasks, management commands, deployment, and testing patterns
External References
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?