Complete AI prompt library for Django developers. Covers Django REST Framework, models & migrations, authentication, Celery background tasks, pytest-django testing, Docker deployment, and performance tuning — all production-ready.
Django in 2026: Battle-Tested Python Web Framework
Django remains the most complete Python web framework — batteries included, ORM, admin, auth, forms, and a mature ecosystem. The developers building the most maintainable Django applications in 2026 use AI prompts that specify the full ORM strategy, DRF serializer design, and security configuration upfront. These are the prompts they use.
1. Project Structure & Settings
You are a senior Django architect who has built multi-tenant SaaS products serving 1M+ users.
Design a production Django 5 project structure for a SaaS application:
- Apps: users, organizations, projects, tasks, billing, notifications, core
- Settings: base.py, development.py, production.py, test.py (split settings pattern)
- Database: PostgreSQL with django-environ for environment variables
- Cache: Redis with django-redis backend
- Media/Static: S3 + CloudFront via django-storages
- Task queue: Celery + Redis broker
- Auth: custom User model (AbstractBaseUser) from day one
Deliver:
1. Full directory tree with one-sentence purpose per file
2. base.py settings with production-safe defaults (DEBUG=False default, explicit ALLOWED_HOSTS)
3. Custom User model with email as username, plus UserManager
4. Requirements split: base.txt, development.txt, production.txt, test.txt
5. The top 3 decisions you would make differently if starting from scratch today
2. Django Models with Proper Indexes
You are a Django ORM expert.
Design Django 5 models for a multi-tenant project management system: Organization, User, Project, Task, Comment, AuditLog.
Requirements:
- Custom User model extending AbstractBaseUser with email login
- SoftDeleteMixin: deleted_at DateTimeField(null=True), custom Manager filtering deleted records
- TimestampMixin: created_at, updated_at with auto_now_add and auto_now
- TenantMixin: organization ForeignKey on every model except Organization itself
- Meta class: indexes for all foreign keys + common filter columns (status, due_date, assigned_to)
- Task model: status choices enum (TODO/IN_PROGRESS/DONE/CANCELLED), priority choices, JSONField for custom_fields
- AuditLog: generic relation (ContentType) to any model, action enum, changed_fields JSONField, actor ForeignKey
- Custom managers: Task.objects.overdue(), Task.objects.assigned_to(user), Project.objects.active()
Output: all model files, managers, mixins, and the initial migration file.
3. Django REST Framework ViewSets
You are a DRF expert building production REST APIs.
Build a complete DRF ViewSet for the Task resource:
ViewSet: TaskViewSet(ModelViewSet)
- queryset: scoped to request.user.organization (never return other tenants' tasks)
- serializer: TaskSerializer (nested assignee, project; writable by slug/id)
- authentication_classes: [JWTAuthentication] (simplejwt)
- permission_classes: [IsAuthenticated, IsOrganizationMember]
- throttle_classes: [UserRateThrottle] — 100/hour for standard, 1000/hour for pro plan
- filter_backends: [DjangoFilterBackend, SearchFilter, OrderingFilter]
- filterset_fields: status, priority, assigned_to, project, due_date (range)
- search_fields: title, description
- ordering_fields: created_at, due_date, priority
Custom actions:
- @action(detail=True, methods=['post']) assign: assign task to user
- @action(detail=False, methods=['get']) overdue: return overdue tasks
Serializer requirements:
- Input: TaskCreateSerializer (flat, validated)
- Output: TaskResponseSerializer (nested, read-optimised)
- Validation: due_date must be in future on create, title min 3 chars
- ORM: select_related('assignee', 'project'), prefetch_related('comments') on list
Output: viewset, serializers, permissions, URL router registration, and queryset optimisation comments.
Why it works: Specifying select_related and prefetch_related explicitly prevents N+1 queries that are the #1 performance problem in DRF APIs. Asking for dual serializers (create vs response) produces the clean separation DRF requires for writable nested relationships.
4. JWT Authentication with simplejwt
You are a Django security engineer.
Configure django-rest-framework-simplejwt for production:
Token settings:
- Access token: 15-minute lifetime, RS256 algorithm (asymmetric keys from env)
- Refresh token: 7-day lifetime, rotate on use, blacklist after rotation (BlacklistMixin)
- Token payload: add user_id, organization_id, role, plan_tier to claims
Custom views:
- POST /auth/login: email + password, return access + refresh, log login event
- POST /auth/refresh: validate, rotate, return new pair
- POST /auth/logout: blacklist refresh token
- GET /auth/me: return current user profile (no DB hit, read from token claims where possible)
Security:
- Brute force: django-ratelimit 5 attempts per 15 minutes per IP on /auth/login
- No user enumeration: identical response for wrong email and wrong password
- Add user_agent and ip_address to login audit log
Output: settings.py JWT config, custom serializers for login/refresh, URL patterns, and the audit log middleware.
5. Django Signals & Async Tasks
You are a Django + Celery expert.
Design the event-driven layer for a project management app:
Django signals (signals.py in each app):
- post_save Task: if status changed to DONE → trigger task_completed signal → notify assignee
- post_save OrganizationMembership (created=True) → send welcome email async
- pre_delete Project → soft-delete all child tasks, create audit log entry
Celery tasks (tasks.py):
- send_task_completion_email(task_id): fetch task, render template, send via Django email backend
- generate_weekly_digest(organization_id): aggregate stats, build HTML report, email to org admins
- cleanup_soft_deleted_records(): periodic task — hard delete records soft-deleted more than 90 days ago
- sync_billing_status(organization_id): call Stripe API, update organization.plan_tier
Celery beat schedule:
- cleanup_soft_deleted_records: daily at 2am UTC
- generate_weekly_digest: Monday 8am UTC per organization (use eta/countdown per org)
Requirements:
- All Celery tasks: retry with exponential backoff (max_retries=3, countdown=60*2**self.request.retries)
- Signal handlers: never perform synchronous IO — always dispatch to Celery
- Idempotency: tasks should be safe to retry (check state before acting)
Output: signals.py, tasks.py, celery.py app config, beat schedule.
6. pytest-django Testing
You are a pytest-django expert.
Write comprehensive tests for the TaskViewSet using pytest-django:
Fixtures (conftest.py):
- django_db fixture with transaction=True
- api_client: DRF APIClient
- auth_client(user): APIClient with JWT token pre-attached
- organization_factory, user_factory, project_factory, task_factory using factory_boy
- mock_celery: override CELERY_TASK_ALWAYS_EAGER=True in settings
Tests for POST /api/tasks/:
1. 201: valid payload — assert response fields, DB record created, Celery task dispatched
2. 400: missing title — assert field-level error key
3. 400: due_date in past — assert field error
4. 401: no token — assert 401 + WWW-Authenticate
5. 403: user from different organization — assert 403
6. Queryset isolation: user A cannot see user B's organization tasks (tenant boundary)
7. Throttle: 6th request within rate limit window returns 429
Use @pytest.mark.django_db. Parametrize validation failure cases.
Show pytest.ini configuration with DJANGO_SETTINGS_MODULE.
7. Performance Optimisation
You are a Django performance engineer.
Audit and optimise this Django view:
[PASTE VIEW + SERIALIZER CODE HERE]
Check and fix:
1. N+1 queries: add select_related() for ForeignKey, prefetch_related() for ManyToMany and reverse FK
2. Queryset evaluation: identify any queryset evaluated inside a loop
3. Database indexes: for every field in filter(), exclude(), order_by() — check if index exists, add if missing
4. Serializer overhead: identify fields computed in Python that could be DB annotations (annotate + F())
5. Caching: identify read-heavy endpoints that can use @cache_page or low-level cache.get/set with Redis
6. Pagination: ensure all list views use LimitOffsetPagination (never return unbounded querysets)
7. select_for_update: identify concurrent write risks, add FOR UPDATE where needed
Output: fixed view, migration adding missing indexes, and Django Debug Toolbar query count before/after.
8. Good vs Bad Django Prompts
| Task | ❌ Bad Prompt | ✅ Good Prompt |
|---|---|---|
| Model design | "Create a Task model" | "Create a Django 5 Task model with: status choices enum, priority choices, soft delete (deleted_at), TimestampMixin, ForeignKey to Project (CASCADE) and User (SET_NULL), JSONField for custom_fields, and Meta indexes on [organization, status, due_date] compound and [assigned_to, status]." |
| API view | "Build a REST API for tasks" | "Build a DRF ModelViewSet for Task: JWT auth, IsOrganizationMember permission, tenant-scoped queryset (filter by request.user.organization), select_related('assignee','project'), DjangoFilterBackend on status/priority/due_date, UserRateThrottle 100/hour, separate create vs response serializers." |
| Testing | "Write tests for my view" | "Write pytest-django tests for POST /api/tasks with factory_boy fixtures. Cover 201 happy path, 400 validation errors (parametrized), 401 no token, 403 cross-tenant access, and 429 rate limit. Assert DB state and Celery task dispatch." |
Generate a custom Django prompt → Try PromptPrepare free
Found this helpful? Share it.