| name | build-django-apps |
| description | Build or modify Django and Django REST Framework applications using the user's preferred service-oriented structure. Use when working on Django settings, Pydantic environment validation, PostgreSQL, DRF APIs without viewsets, serializers, services, schemas, constants, media/static storage, Docker, tests, migrations, or drf-spectacular OpenAPI docs. |
Build Django Apps
Core Defaults
Build Django apps with a service-oriented DRF structure. Keep models lean, serializers focused on validation and representation, APIs focused on request/response handling, and business rules in services.
Use Python 3.12+, uv, Ruff, Pyright basic mode, pytest, pytest-django, DRF, drf-spectacular, Pydantic settings, PostgreSQL, WhiteNoise, Cloudflare R2 media storage, and environment-specific settings unless the existing project has different pinned tools.
Ensure new Python code is typed. Add parameter and return annotations to functions, methods, services, serializers where practical, and helper utilities.
Project Structure
Use this default layout:
src/
├── manage.py
├── config/
│ ├── urls.py
│ ├── asgi.py
│ ├── wsgi.py
│ ├── drf_spectacular_schema.py
│ └── settings/
│ ├── __init__.py
│ ├── base.py
│ ├── dev.py
│ ├── test.py
│ ├── staging.py
│ └── prod.py
└── app_name/
├── apis/
├── models/
├── serializers/
├── services/
├── schemas/
├── types/
├── constants.py
├── migrations/
├── urls.py
└── admin.py
tests/
Use config/settings/__init__.py to select the concrete settings module from the environment, following the existing project convention.
Use constants.py for constants shared across files in the Django app. Keep constants close to the app when they are app-specific; only promote them to project-level config when multiple apps need them.
Models
Keep models lean. Use a shared abstract base model for:
- UUIDv7 primary key.
created_at = auto_now_add.
updated_at = auto_now.
Add database constraints and indexes in models where they enforce real invariants. Prefer TextChoices for stable choice fields. Use __str__ for readable admin/debug output.
Avoid putting workflows, permission decisions, or cross-model orchestration in model methods. Small normalization in save() is acceptable when it is intrinsic to the model field.
APIs, Serializers, And Services
Use DRF API classes for endpoint behavior. Do not use DRF viewsets.
apis: view classes, queryset selection, serializer selection, permissions, and drf-spectacular decorators.
serializers: field definitions, validation, representation, and delegation to services for create/update/delete.
services: business logic, uniqueness checks, workflow orchestration, cross-model writes, and domain validation.
schemas: drf-spectacular schema constants and examples.
types: permission constants, enums, and shared type definitions.
Each file in apis, serializers, services, and schemas should correspond to one model or one grouped piece of business logic. Keep names aligned across folders when possible, such as apis/gates.py, serializers/gates.py, services/gates.py, and schemas/gates.py.
Permissions should be explicit per method when endpoint access differs across HTTP methods.
Configuration And Integrations
Keep integration setup in config or libs-like modules, not in API classes:
- Pydantic
BaseSettings validation for environment variables
- PostgreSQL database configuration
- database URL parsing with
dj_database_url
- atomic database transactions via
ATOMIC_REQUESTS
- CORS
- Sentry
- static files through WhiteNoise
- media files and uploads through Cloudflare R2
- auth clients
- Redis
- OpenAPI
Use drf-spectacular for OpenAPI docs and keep schema metadata close to the API surface.
For settings:
- Define a typed settings object with Pydantic
BaseSettings or pydantic-settings.
- Validate required environment variables at startup.
- Parse
DATABASE_URL with dj_database_url.
- Configure PostgreSQL as the database backend.
- Set
DATABASES["default"]["ATOMIC_REQUESTS"] = True.
- Configure WhiteNoise middleware and static file storage for static assets.
- Configure Cloudflare R2/S3-compatible storage for media files and uploads, using env vars for endpoint URL, bucket, access key, secret key, and public/custom domain if available.
- Keep secrets out of source code and logs.
Docker
Dockerize Django apps by default when building a deployable app. Put the container entrypoint command inside the Dockerfile itself rather than relying on a separate entrypoint script.
The Docker setup should:
- Install dependencies with the project package manager.
- Copy application code.
- Collect static files when appropriate for the image/build mode.
- Run migrations through an explicit release/deploy command or documented operational target, not hidden inside an opaque shell script.
- Start the app with Gunicorn or the existing production ASGI/WSGI server.
- Use environment variables for all runtime config.
Testing And Verification
Use pytest and pytest-django:
- Service tests for business rules.
- API tests for auth, permissions, validation, and response shape.
- Factory modules for repeated model setup.
- Migration tests when changing constraints or data shape.
Run the closest available checks:
uv run ruff check .
uv run ruff format --check .
uv run pyright
uv run pytest
uv run python src/manage.py makemigrations --check --dry-run when model changes should not create migrations.