django-env-doctor
Validate, load, and report on Django environment variables — all in one place.
The problem
Every Django developer has hit this at some point:
- App crashes at startup with
KeyErrorbecause a new env var was added but not documented - Teammate clones the repo and has no idea what goes in
.env - Deployment fails because an env var is set to
"true"but the code expects a boolean - You find out a required variable is missing only after the server is already live
django-env-doctor solves all of this with a single object in your settings.py.
Features
- Load
.envfiles intoos.environ - Declare all env variables in a single schema
- Type casting —
str,int,float,bool,url,email,json,list,path - Required field validation with a clear error at startup
- Default value support
- Validation rules —
min,max,min_length,max_length,choices - Reports all missing/invalid vars at once instead of failing one by one
- CLI command
manage.py env_doctorwith a clean health report - CI-friendly exit codes —
0for clean,1for issues - Auto-generate
.env.examplefrom your schema (always in sync) - Secret masking — sensitive values are never shown in logs or reports
- Optional loading — use as a validator-only on top of existing loaders
- Django system checks integration (
manage.py check) - Multi-environment support — different rules for
dev,staging,prod - Zero runtime dependencies
Installation
pip install django-env-doctor
Quick start
Replace the scattered os.environ.get() calls in your settings.py with one DjangoEnv instance:
# settings.py
from django_env_doctor import DjangoEnv
env = DjangoEnv(
schema={
"SECRET_KEY": {
"type": "str",
"required": True,
"secret": True,
"min_length": 40,
"description": "Django secret key",
},
"DEBUG": {
"type": "bool",
"default": False,
"description": "Enable debug mode",
},
"DATABASE_URL": {
"type": "url",
"required": True,
"description": "Primary database connection URL",
},
"ALLOWED_HOSTS": {
"type": "list",
"default": [],
"description": "Comma-separated list of allowed hosts",
},
"MAX_UPLOAD_MB": {
"type": "int",
"default": 10,
"min": 1,
"max": 100,
"description": "Maximum file upload size in megabytes",
},
"ADMIN_EMAIL": {
"type": "email",
"required": False,
"description": "Admin notification email",
},
"SENTRY_DSN": {
"type": "url",
"required": True,
"environments": ["production", "staging"],
"description": "Sentry error tracking DSN",
},
},
load_file=True, # Load .env file automatically
env_file=".env", # Path to .env file
raise_on_error=True, # Raise at startup if required vars are missing
)
# Use the validated values directly
SECRET_KEY = env("SECRET_KEY")
DEBUG = env("DEBUG")
ALLOWED_HOSTS = env("ALLOWED_HOSTS")
MAX_UPLOAD_MB = env("MAX_UPLOAD_MB")
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
# DATABASE_URL is validated and available
}
}
Schema definition
Each variable in the schema accepts the following options:
| Option | Type | Default | Description |
|---|---|---|---|
type |
str | "str" |
Variable type. See supported types below. |
required |
bool | True |
Whether the variable must be set. |
default |
any | None |
Default value if the variable is not set. |
description |
str | "" |
Human-readable description. Used in .env.example. |
secret |
bool | False |
If True, value is masked in reports and logs. |
min_length |
int | None |
Minimum string or list length. |
max_length |
int | None |
Maximum string or list length. |
min |
float | None |
Minimum numeric value. |
max |
float | None |
Maximum numeric value. |
choices |
list | None |
Value must be one of the listed choices. |
environments |
list of str | None |
Only validate this var in specific environments. |
Supported types
| Type | Example value | Python result |
|---|---|---|
str |
"hello" |
"hello" |
int |
"42" |
42 |
float |
"3.14" |
3.14 |
bool |
"true", "1", "yes" |
True |
url |
"https://example.com" |
"https://example.com" |
email |
"user@example.com" |
"user@example.com" |
json |
'{"key": "val"}' |
{"key": "val"} |
list |
"a,b,c" or '["a","b"]' |
["a", "b", "c"] |
path |
"~/media" |
"/home/user/media" |
CLI health report
Run this any time to see the status of your environment:
python manage.py env_doctor
Example output:
django-env-doctor [production]
------------------------------------------------------------
[ OK ] SECRET_KEY *** hidden ***
[ OK ] DEBUG → False (default)
[MISSING] DATABASE_URL Required variable is not set
[ SKIP ] ADMIN_EMAIL Optional, not set
[INVALID] MAX_UPLOAD_MB Value must be <= 100
[ OK ] ALLOWED_HOSTS → set
------------------------------------------------------------
Total: 6 OK: 3 Missing: 1 Invalid: 1 Warn: 0 Skip: 1
2 issue(s) found. Your app may not start correctly.
Additional options
# Show actual values (secrets always hidden)
python manage.py env_doctor --show-values
# CI mode: plain text output, exit code 1 on issues
python manage.py env_doctor --ci
# Generate .env.example from your schema
python manage.py env_doctor --export-example
# Custom output path for example file
python manage.py env_doctor --export-example --example-output config/.env.example
Generate .env.example automatically
python manage.py env_doctor --export-example
This generates a .env.example that stays in sync with your schema:
# .env.example
# Auto-generated by django-env-doctor
# Do NOT commit your actual .env file — only this example.
# Django secret key
# [type=str, required, secret]
SECRET_KEY=your-secret-secret-key
# Enable debug mode
# [type=bool, optional]
DEBUG=False
# Primary database connection URL
# [type=url, required]
DATABASE_URL=
Use as validator only (no file loading)
If you already use python-dotenv or django-environ to load your .env file, you can use django-env-doctor purely for validation:
env = DjangoEnv(
schema={...},
load_file=False, # Don't load .env — just validate what's already in os.environ
raise_on_error=True,
)
Multi-environment support
Mark variables as only required in specific environments:
env = DjangoEnv(
schema={
"SENTRY_DSN": {
"type": "url",
"required": True,
"environments": ["production", "staging"],
},
"DEBUG": {
"type": "bool",
"default": False,
},
},
current_environment=os.environ.get("DJANGO_ENV", "development"),
)
SENTRY_DSN will only be required when DJANGO_ENV is production or staging.
Django system checks integration
# settings.py or apps.py
from django_env_doctor import DjangoEnv, register_system_checks
env = DjangoEnv(schema={...}, raise_on_error=False)
register_system_checks(env.results)
Issues will now appear in python manage.py check:
SystemCheckError: System check identified some issues:
ERRORS:
?: (env_doctor.E001) Required environment variable 'DATABASE_URL' is not set.
HINT: Add DATABASE_URL to your .env file or environment.
CI integration
# In your CI pipeline
python manage.py env_doctor --ci
# Exits with code 1 if any required variables are missing or invalid
Running tests
pip install -e ".[dev]"
pytest
pytest --cov=django_env_doctor
Contributing
Contributions are welcome. Please open an issue first to discuss what you'd like to change.
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Write tests for your changes
- Run the test suite (
pytest) - Submit a pull request
License
MIT — see LICENSE for details.
Release files for django-env-doctor 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| django_env_doctor-0.1.0.tar.gz | 22.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_env_doctor-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 45.3 kB
Release files / django_env_doctor-0.1.0.tar.gz
| Download URL | django_env_doctor-0.1.0.tar.gz |
|---|---|
| Size | 22.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0239cb129f39a03b162f0448035c859385d91677c1f833e29523a2c07d7eed1b
|
|
BLAKE2b-256 checksum How to use checksums |
3a6462377e3c695f72342d5a05fd91febeb620c79545d6cacb592dfc116b93e6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.9
|
Release files / django_env_doctor-0.1.0-py3-none-any.whl
| Download URL | django_env_doctor-0.1.0-py3-none-any.whl |
|---|---|
| Size | 22.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bb0b3303b3de6ac6b839d29091f23a5b94d1e11cdf2c0c911b3f3380b93e7908
|
|
BLAKE2b-256 checksum How to use checksums |
7e834988dc5c5b44d7c1429563dc15375a9cbdeadebac6323fb47d47190d04de
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.9
|