This file provides guidance to AI coding agents when working with code in this repository.
cookiecutter-django is a Cookiecutter template that generates production-ready Django projects. It is NOT a Django application itself — it's a Jinja2-templated project scaffold. The generated project lives inside {{cookiecutter.project_slug}}/ and gets processed by Cookiecutter when users run the generator.
uv sync --locked# Full test suite (parallel, via tox)
uv run tox run -e py
# Direct pytest (parallel)
uv run pytest -n auto tests
# Single test
uv run pytest tests/test_cookiecutter_generation.py -k "test_name"
# Run with auto-fixable style checks enabled
AUTOFIXABLE_STYLES=1 uv run pytest -n auto tests# Run all pre-commit hooks
uv run pre-commit run --all-files
# Ruff only
uv run ruff check --fix
uv run ruff format# Docker-based
sh tests/test_docker.sh # defaults
sh tests/test_docker.sh use_celery=y use_drf=y # with options
# Bare metal (needs PostgreSQL and Redis running)
sh tests/test_bare.sh
sh tests/test_bare.sh use_celery=y frontend_pipeline=Gulpuv run cookiecutter . --no-input --output-dir=/tmp/debug- User runs
cookiecutter— prompted with options fromcookiecutter.json hooks/pre_gen_project.pyvalidates input (project_slug format, conflicting options)- Jinja2 renders all files under
{{cookiecutter.project_slug}}/with user choices hooks/post_gen_project.py(~550 lines) removes files not needed for the chosen options, generates random secrets, and adjusts config files
cookiecutter.json— All template variables and their choices (project name, Docker, Celery, cloud provider, frontend pipeline, etc.)hooks/pre_gen_project.py— Pre-generation validation (uses Jinja2 syntax at the top for context manipulation)hooks/post_gen_project.py— Post-generation cleanup: removes files based on user choices, generates Django secret key, sets DB credentials, modifies package.json and .pre-commit-config.yaml{{cookiecutter.project_slug}}/— The template directory; files here use Jinja2 conditionals ({% if cookiecutter.use_celery == 'y' %}) to include/exclude content
tests/test_cookiecutter_generation.py— Main test file. Usespytest-cookiesto bake the template with 50+ option combinations defined inSUPPORTED_COMBINATIONS. Verifies: no Jinja syntax left in output, generated code passes linting, correct files present/absent. Skips on Windows (sh module) and macOS CI (slow).tests/test_hooks.py— Unit tests for hook helper functionstests/test_bare.sh/tests/test_docker.sh— Integration tests that generate a project and run its full test suite
The generated Django project uses:
config/settings/{base,local,test,production}.py— Split settings with django-environconfig/urls.py— URL routing<project_slug>/users/— Custom user model (username or email-based auth via django-allauth)compose/— Docker configs for local and productionrequirements/— Not used; dependencies managed viapyproject.toml+uv.lock
- Python 3.14 required (
requires-python = "==3.14.*") - Line length: 119 characters (ruff and djlint)
- Ruff for linting/formatting; config in
pyproject.tomlunder[tool.ruff] - djLint for HTML template linting with
profile = "jinja" - Template files under
{{cookiecutter.project_slug}}/are excluded from ruff (not parseable Python) - Calendar versioning:
YYYY.MM.DD
- Add the variable and choices to
cookiecutter.json - Add validation in
hooks/pre_gen_project.pyif needed - Add file removal/modification logic in
hooks/post_gen_project.py - Use Jinja2 conditionals in template files:
{% if cookiecutter.option == 'y' %} - Add test combinations to
SUPPORTED_COMBINATIONSintests/test_cookiecutter_generation.py