From qe-framework
Creates Django models with proper indexes, optimizes ORM queries with select_related/prefetch_related, builds DRF serializers and viewsets, and configures JWT authentication for Django web apps and REST APIs.
How this skill is triggered — by the user, by Claude, or both
Slash command
/qe-framework:Qdjango-expertThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Senior Django specialist with deep expertise in Django 5.0, Django REST Framework, and production-grade web applications.
Senior Django specialist with deep expertise in Django 5.0, Django REST Framework, and production-grade web applications.
manage.py makemigrations and manage.py migrate; verify schema before proceedingAPITestCase or curl check before adding authLoad detailed guidance based on context:
| Topic | Reference | Load When |
|---|---|---|
| Models | references/models-orm.md | Creating models, ORM queries, optimization |
| Serializers | references/drf-serializers.md | DRF serializers, validation |
| ViewSets | references/viewsets-views.md | Views, viewsets, async views |
| Authentication | references/authentication.md | JWT, permissions, SimpleJWT |
| Testing | references/testing-django.md | APITestCase, fixtures, factories |
The snippet below demonstrates the core MUST DO constraints: indexed fields, select_related, serializer validation, and endpoint permissions.
# models.py
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=255, db_index=True)
author = models.ForeignKey(
"auth.User", on_delete=models.CASCADE, related_name="articles"
)
published_at = models.DateTimeField(auto_now_add=True, db_index=True)
class Meta:
ordering = ["-published_at"]
indexes = [models.Index(fields=["author", "published_at"])]
def __str__(self):
return self.title
# serializers.py
from rest_framework import serializers
from .models import Article
class ArticleSerializer(serializers.ModelSerializer):
author_username = serializers.CharField(source="author.username", read_only=True)
class Meta:
model = Article
fields = ["id", "title", "author_username", "published_at"]
def validate_title(self, value):
if len(value.strip()) < 3:
raise serializers.ValidationError("Title must be at least 3 characters.")
return value.strip()
# views.py
from rest_framework import viewsets, permissions
from .models import Article
from .serializers import ArticleSerializer
class ArticleViewSet(viewsets.ModelViewSet):
"""
Uses select_related to avoid N+1 on author lookups.
IsAuthenticatedOrReadOnly: safe methods are public, writes require auth.
"""
serializer_class = ArticleSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def get_queryset(self):
return Article.objects.select_related("author").all()
def perform_create(self, serializer):
serializer.save(author=self.request.user)
# tests.py
from rest_framework.test import APITestCase
from rest_framework import status
from django.contrib.auth.models import User
class ArticleAPITest(APITestCase):
def setUp(self):
self.user = User.objects.create_user("alice", password="pass")
def test_list_public(self):
res = self.client.get("/api/articles/")
self.assertEqual(res.status_code, status.HTTP_200_OK)
def test_create_requires_auth(self):
res = self.client.post("/api/articles/", {"title": "Test"})
self.assertEqual(res.status_code, status.HTTP_403_FORBIDDEN)
def test_create_authenticated(self):
self.client.force_authenticate(self.user)
res = self.client.post("/api/articles/", {"title": "Hello Django"})
self.assertEqual(res.status_code, status.HTTP_201_CREATED)
select_related/prefetch_related for related objectsWhen implementing Django features, provide:
class PublishedManager(models.Manager):
"""Custom manager filtering published articles."""
def get_queryset(self):
return super().get_queryset().filter(is_published=True)
class Article(models.Model):
"""Article model with published timestamp and custom manager."""
title = models.CharField(max_length=255, db_index=True)
author = models.ForeignKey("auth.User", on_delete=models.CASCADE)
is_published = models.BooleanField(default=False)
published_at = models.DateTimeField(null=True, db_index=True)
objects = PublishedManager()
class ExceptionMiddleware:
"""Catch validation and permission errors, return JSON."""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
try:
return self.get_response(request)
except PermissionDenied:
return JsonResponse({"error": "Forbidden"}, status=403)
class ArticleSerializer(serializers.ModelSerializer):
"""Validates title length, returns nested author."""
def validate_title(self, value):
if len(value) < 3:
raise serializers.ValidationError("Min 3 chars")
return value
class IsAuthorOrReadOnly(permissions.BasePermission):
"""Allow edit only if request user is author."""
def has_object_permission(self, request, view, obj):
return request.method in SAFE_METHODS or obj.author == request.user
def publish_article(article_id: int) -> Article:
"""Publish an article by ID.
Args:
article_id: Primary key of Article to publish.
Returns:
Updated Article with is_published=True.
Raises:
Article.DoesNotExist: If article not found.
"""
select = ["E", "F", "W", "I001"] (errors, undefined, warnings, imports)pyproject.toml with [tool.black], [tool.mypy], [tool.ruff]raw() and string interpolation in queries|safe on user inputCsrfViewMiddleware enabled in MIDDLEWARE; POST requires {% csrf_token %}fields in serializers; never use fields = "__all__" with untrusted inputos.environ, never hardcode; rotate in productionFalse in production to hide stack traces| Wrong | Correct |
|---|---|
| View with 200+ lines of business logic | Extract to service classes or model managers |
Article.objects.filter(author=user) in loop | Use prefetch_related("author") at query time |
| No index on frequently filtered fields | Add db_index=True or Meta.indexes |
Validation and calculations in serializer create() | Move to model methods or service layer |
Article.objects.raw("SELECT * FROM ...") | Use ORM QuerySet; parameterize if raw needed |
Django 5.0, DRF, async views, ORM, QuerySet, select_related, prefetch_related, SimpleJWT, django-filter, drf-spectacular, pytest-django
npx claudepluginhub inho-team/qe-framework --plugin qe-frameworkCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.