From nation-of-elites
Django best practices, ORM optimization, and REST API patterns for building scalable Python web applications
How this skill is triggered — by the user, by Claude, or both
Slash command
/nation-of-elites:django-patternsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
- Building Django REST API backends
django-expert - Primary user for Django-specific developmentbackend-developer - General backend development with Djangoapi-architect - REST API design using Django REST FrameworkUse Django REST Framework's class-based views:
APIView - For custom logic and complex operationsViewSet - For standard CRUD operationsGenericAPIView with mixins - For common patterns with customizationfrom rest_framework import viewsets, permissions
from rest_framework.decorators import action
from rest_framework.response import Response
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [permissions.IsAuthenticated]
@action(detail=True, methods=['post'])
def set_password(self, request, pk=None):
user = self.get_object()
serializer = PasswordSerializer(data=request.data)
if serializer.is_valid():
user.set_password(serializer.validated_data['password'])
user.save()
return Response({'status': 'password set'})
return Response(serializer.errors, status=400)
Recommended JWT Authentication Stack:
# settings.py
INSTALLED_APPS = [
...
'rest_framework',
'rest_framework_simplejwt',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
}
from datetime import timedelta
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
}
Custom User Model (Always Recommended):
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.db import models
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name']
objects = CustomUserManager()
Query Optimization Patterns:
# ❌ N+1 Query Problem
for post in Post.objects.all():
print(post.author.name) # Hits database for each post!
# ✅ Use select_related for ForeignKey
posts = Post.objects.select_related('author').all()
for post in posts:
print(post.author.name) # Single query with JOIN
# ✅ Use prefetch_related for ManyToMany
posts = Post.objects.prefetch_related('tags').all()
for post in posts:
print(post.tags.all()) # Efficient prefetching
# ✅ Combine both for complex queries
posts = Post.objects.select_related('author').prefetch_related('tags', 'comments__user').all()
Database Indexing:
class Article(models.Model):
title = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(unique=True, db_index=True)
created_at = models.DateTimeField(auto_now_add=True, db_index=True)
class Meta:
indexes = [
models.Index(fields=['created_at', '-id']), # Compound index
models.Index(fields=['author', 'status']), # Common filter combo
]
Nested Serializers:
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = ['id', 'name', 'email']
class PostSerializer(serializers.ModelSerializer):
author = AuthorSerializer(read_only=True)
author_id = serializers.PrimaryKeyRelatedField(
queryset=Author.objects.all(),
source='author',
write_only=True
)
class Meta:
model = Post
fields = ['id', 'title', 'content', 'author', 'author_id', 'created_at']
Dynamic Field Selection:
class DynamicFieldsModelSerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs):
fields = kwargs.pop('fields', None)
super().__init__(*args, **kwargs)
if fields is not None:
allowed = set(fields)
existing = set(self.fields)
for field_name in existing - allowed:
self.fields.pop(field_name)
# Usage: PostSerializer(post, fields=['id', 'title'])
Recommended Django Project Layout:
project_name/
├── manage.py
├── config/
│ ├── __init__.py
│ ├── settings/
│ │ ├── __init__.py
│ │ ├── base.py # Common settings
│ │ ├── dev.py # Development
│ │ ├── prod.py # Production
│ │ └── test.py # Testing
│ ├── urls.py
│ └── wsgi.py
├── apps/
│ ├── users/
│ │ ├── __init__.py
│ │ ├── models.py
│ │ ├── serializers.py
│ │ ├── views.py
│ │ ├── urls.py
│ │ └── tests/
│ ├── posts/
│ └── comments/
└── requirements/
├── base.txt
├── dev.txt
└── prod.txt
Custom Exception Handler:
# exceptions.py
from rest_framework.views import exception_handler
from rest_framework.response import Response
def custom_exception_handler(exc, context):
response = exception_handler(exc, context)
if response is not None:
response.data = {
'error': {
'status_code': response.status_code,
'message': response.data.get('detail', str(exc)),
'errors': response.data if isinstance(response.data, dict) else {}
}
}
return response
# settings.py
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'project.exceptions.custom_exception_handler'
}
API Test Example:
from rest_framework.test import APITestCase
from rest_framework import status
from django.contrib.auth import get_user_model
User = get_user_model()
class PostAPITestCase(APITestCase):
def setUp(self):
self.user = User.objects.create_user(
email='[email protected]',
password='testpass123'
)
self.client.force_authenticate(user=self.user)
def test_create_post(self):
url = '/api/posts/'
data = {'title': 'Test Post', 'content': 'Test content'}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data['title'], 'Test Post')
self.assertEqual(response.data['author']['id'], self.user.id)
django-environ)PageNumberPagination)@transaction.atomic)For more advanced patterns, see:
npx claudepluginhub advisely/claude-code-agents-team-nation-of-elites --plugin nation-of-elitesGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.