Skip to content

Django Project Instructions

Claude CodeCLAUDE.mdCoding

CLAUDE.md for Django projects: app structure, ORM query rules, migration workflow, layered settings, and pytest-django conventions agents must follow before touching models.

Use when: Use in a Django 5.x codebase so agents handle migrations safely, keep business logic out of views, and avoid N+1 queries when writing or reviewing ORM code.

@library0 upvotes0 remixes0 comments

Get this skill

Add the skill file with the CLI, by hand, or over MCP.

Save this to your project or home directory so Claude Code can load it.

npx goodprompts add django-project-claude-md
Saves to./CLAUDE.md
npx goodprompts add django-project-claude-md
Saves to ./CLAUDE.md

Skill file

CLAUDE.md3,456 characters
# Project Instructions — Django
## Commands
```bash
uv run python manage.py runserver # dev server → http://localhost:8000
uv run pytest # full test suite (pytest-django, not manage.py test)
uv run pytest apps/orders -x # focused run while iterating
uv run python manage.py makemigrations # after any model change
uv run python manage.py migrate # apply locally
uv run python manage.py makemigrations --check --dry-run # CI gate: fails if migrations are missing
uv run ruff format . && uv run ruff check --fix .
```
## App structure
Apps live under `apps/` and are small and domain-focused (`apps/orders`, `apps/accounts`). Standard layout per app:
```
apps/orders/
models.py # schema only: fields, Meta, constraints, simple properties
services.py # business logic — all writes go through functions here
selectors.py # read queries used by views/tasks
views.py / api.py
admin.py
migrations/
tests/
```
- **Views stay thin.** A view parses input, calls one service/selector function, returns a response. If a view grows conditional business logic, move it to `services.py`.
- Cross-app imports go through the other app's `services.py`/`selectors.py`, never its models' managers directly.
## ORM rules
- Every queryset that touches related objects in a loop uses `select_related` (FK/one-to-one) or `prefetch_related` (many). When you add a template loop or serializer over a queryset, check for N+1 explicitly.
- Use `.exists()` instead of `len()`/truthiness for existence checks, `.count()` instead of `len(qs)`, `.update()`/`.bulk_create()` for bulk writes.
- Wrap multi-step writes in `transaction.atomic()`; trigger side effects (emails, webhooks) via `transaction.on_commit`.
- Enforce invariants in the database: `UniqueConstraint`/`CheckConstraint` in `Meta.constraints`, not just `clean()` methods.
- Custom managers/querysets for reusable filters: `Order.objects.unpaid()` rather than repeating `.filter(status="unpaid")`.
## Migrations
- Never edit an applied migration. To change one that has shipped, add a new migration.
- One logical change per migration; name it: `makemigrations orders -n add_refund_status`.
- Data migrations use `apps.get_model("orders", "Order")` — never import models directly into a migration.
- Adding a non-nullable field to a populated table happens in two deploys: (1) add nullable + backfill, (2) make it non-nullable. Flag this in your summary whenever it applies.
- After model changes, run the `--check --dry-run` command above to confirm nothing is missing.
## Settings
```
config/settings/base.py # everything shared
config/settings/local.py # dev: DEBUG=True, console email
config/settings/production.py
```
- Secrets and per-environment values come from environment variables via `django-environ` — never hardcode them in any settings file.
- New settings go in `base.py` with a safe default; override per environment only when values genuinely differ.
## Tests (pytest-django)
- Plain test functions with the `db` fixture / `@pytest.mark.django_db`; no `TestCase` classes in new code.
- Build objects with `factory_boy` factories in `apps/<app>/tests/factories.py` — never fixtures-as-JSON.
- Test services and selectors directly; test views only for status codes, permissions, and serialization shape.
- Assert query efficiency on hot paths with `django_assert_num_queries`.
Comments

Comments

Sign in to commentSign in

Remixes

Loading remixes…