Django Best Practices

by Convext

Public

Django framework guidelines and standards

go

Rules (56)

Config

high Use environment variables for configuration

Config in env vars, not code. Never commit .env. Commit .env.example. Never hardcode secrets.

Database

critical Never store sensitive data in plain text

Passwords: bcrypt. API keys: encrypt. PII: field-level encryption. Never log sensitive data.

Dependencies

critical Always use latest dependency versions

Use latest stable versions. Fix breaking changes—don't avoid upgrades. Check official registries.

Django

high Use Django REST Framework for APIs

DRF serializers for validation. ViewSets for CRUD. Token/JWT auth. Pagination on list endpoints.

high Use Django ORM properly

select_related/prefetch_related for joins. Use F() and Q() objects. Avoid N+1 with django-debug-toolbar.

high Use Django migrations properly

One migration per change. Never edit applied migrations. Use RunPython for data migrations. Squash when large.

medium Use Django forms for validation

Forms/ModelForms for input validation. Clean methods for business logic. Never trust request.POST directly.

Fastapi

high Use dependency injection

Use `Depends()` for db sessions, auth, config, services. Composable and testable.

high Use async database operations

Async drivers: asyncpg (Postgres), SQLAlchemy 2.0 async. Match FastAPI's async nature.

high Use Pydantic models for request/response

Explicit Pydantic models for all inputs/outputs. Auto-validation, docs, type safety.

Flask

high Use Flask application factory

`create_app()` factory pattern. Config from env. Blueprints for modularity. Flask extensions for features.

high Use Flask-SQLAlchemy properly

Flask-SQLAlchemy for ORM. Flask-Migrate for migrations. Scoped sessions. Avoid circular imports.

Formatting

medium Use isort for Python imports

isort for import ordering. Profile: black. Run before Black. Or use Ruff which includes isort.

Git

medium Atomic commits with Conventional Commits

Small, focused commits. Use: feat/fix/refactor/test/docs/chore. Each commit independently deployable.

Linting

high Use mypy for Python type checking

mypy with --strict mode. Check all files. Fix type errors, don't ignore. Part of CI pipeline.

medium Use pyright for Python type checking

pyright: fast type checker. VS Code Pylance backend. strict or basic mode. Better inference than mypy.

medium Use flake8 for Python linting

flake8 for style checks. Use with .flake8 config. max-line-length: 88 (Black compat). Ruff is faster alternative.

Llm Behavior

critical No rationalizations

No excuses: 'pre-existing', 'unrelated', 'tedious', 'for now'. Recognize and continue working.

critical Own all code in the repository

You wrote every line. No 'pre-existing issues'—only issues you haven't fixed yet.

critical User defines success

User and tests define done. Don't redefine scope or declare partial progress as complete.

Package Manager

medium Use pip with requirements.txt

requirements.txt with pinned versions. `pip freeze > requirements.txt`. Virtual environments. Prefer uv.

medium Use Poetry for Python dependency management

pyproject.toml + poetry.lock. `poetry install --no-dev` for prod. Groups for dev deps. Prefer uv for speed.

Python

critical Use uv for package management

Use `uv` (not pip/poetry/pipenv). 100x faster, lockfile support, built-in venv. Commands: `uv add`, `uv run`.

high Use type hints everywhere

Type hints on all functions and class attributes. Enables mypy/pyright static analysis.

high Use Ruff for linting and formatting

Ruff for both linting and formatting (replaces flake8/isort/pylint/Black). Single tool, 100x faster. `ruff check` and `ruff format`.

high Use logging module properly

logging module, not print. Configure at app entry point. Use __name__ for logger names. Structured logging with extra dict or structlog.

high Use context managers for resources

with statement for files, connections, locks. contextlib for custom managers. Never leave resources open. async with for async resources.

high Use async/await for I/O operations

Async for HTTP (httpx), database (asyncpg), files (aiofiles). Don't mix sync/async in same service.

high Use Pydantic for data validation

Pydantic BaseModel for validation. Field types with constraints. Serialization built-in. FastAPI integration.

high Use SQLAlchemy for database access

SQLAlchemy 2.0 style. Declarative models. Session management. Async with asyncio extension.

high uv project structure

pyproject.toml for deps, uv.lock (commit it), .python-version, src/ layout. Python 3.12+.

high Use Alembic for database migrations

Alembic for SQLAlchemy migrations. `alembic revision --autogenerate`. Review generated migrations. Stamp for sync.

medium Use boto3 for AWS

boto3 for AWS services. Use resource API for simple ops, client for advanced. Handle pagination.

medium Use dataclasses or Pydantic for data structures

Dataclasses for simple containers, Pydantic for validation. No plain dicts for structured data.

medium uv scripts and commands

Define entry points in `[project.scripts]`. Run any command with `uv run <cmd>`. CI: `uv sync --frozen`.

medium uv workspaces for monorepos

Use `[tool.uv.workspace]` for multi-package repos. Single lockfile, editable local packages.

medium Use pytest for testing

pytest with fixtures and parametrize. Simple asserts, rich plugin ecosystem.

medium Use Celery for distributed tasks

Celery for distributed task queue. Redis or RabbitMQ broker. Beat for scheduling. Flower for monitoring.

medium Migrate from pipenv to uv

pipenv is slow and unmaintained. Migrate to uv for speed and modern features. `uv init` from existing.

medium Use unittest for Python basics

unittest for simple cases or legacy code. TestCase classes. setUp/tearDown. Prefer pytest for new projects.

medium Use pylint for comprehensive Python linting

pylint for comprehensive checks. Disable noisy rules in pylintrc. Ruff is faster alternative.

medium Use httpx for async HTTP

httpx for async HTTP client. Requests-compatible API. Async context manager. HTTP/2 support.

medium Use requests for sync HTTP

requests for simple sync HTTP. Session for connection pooling. Timeout always. Use httpx for async.

Rails

critical Use Rails credentials for secrets

Rails.application.credentials for secrets. `rails credentials:edit`. Environment-specific credentials. Never commit master.key.

Security

critical Validate and sanitize all user input

Allowlists, not denylists. Validate type/length/format. Sanitize HTML. Parameterized queries only.

critical Use HTTPS everywhere

Force SSL, redirect HTTP→HTTPS, secure cookies (Secure/HttpOnly/SameSite), HSTS headers.

critical Implement proper authentication and authorization

Auth: bcrypt/argon2 for passwords, rate limiting, secure sessions/tokens. Authz: check permissions on every request, use policy objects or middleware.

Testing

critical No mocking the class under test

Test real instances. Mocking the class under test hides bugs.

critical Never ignore failing tests

Fix failures immediately. No skipping, no "pre-existing issues." Own the codebase state—a test suite with ignored tests can't be trusted.

high TDD: Red -> Green -> Refactor

1) Write failing test 2) Minimum code to pass 3) Refactor. Every line has a reason.

high Test behavior, not implementation

Test public interfaces, inputs/outputs. Tests must survive refactoring. Don't test private methods.

high Mock only at external boundaries

Mock only: external HTTP APIs, time, filesystem side effects, third-party services. Use real implementations for internal services, database, and business logic.

medium One assertion per test (conceptually)

One logical concept per test. Multiple asserts OK if same concept. Clear test names describing behavior.

medium Use fixtures or factories for test data

Use consistent test data setup: fixtures for stable reference data, factories for dynamic scenarios. Avoid inline object creation scattered throughout tests.

Workflow

critical Code must work locally before pushing

Verify changes locally: run app, run tests, check for errors. CI catches environment issues, not basic bugs.

high Run formatter, linter, and tests before commit

Format → Lint → Test before every commit. Never rely on CI for basic checks.

Language Standards (1)

go
Linter: golangci-lint Formatter: gofmt

Use this Ruleset

Sign in to adopt or fork this ruleset

Sign in with GitHub

Statistics

Rules
56
Standards
1
Projects using
0
Created
Jan 15, 2026