How to Split Django settings.py
Splitting django settings into multiple files with varying responsibilities enhances readability and maintainability, especially in very large and complex projects.
Splitting Django’s settings.py is one of the most valuable structural upgrades you can make. For small tutorials, a single settings file is fine.
For real projects, having one file eventually becomes painful: - development vs production differences - secrets handling - test config - Channels / Celery / Redis variants - cloud storage config - logging complexity - growing technical debt
This article explains two correct ways to split settings: 1. Right after starting a new Django project 2. After the project already exists
Both approaches matter, because the migration path is different.
Why Split Settings at All?
A single file usually becomes: settings.py # 800+ lines
Containing: - dev config - prod config - debug flags - test overrides - secrets - database switching - duplicated conditionals
That becomes hard to read and manage as the file becomes larger and containes either overlapping or mutuall exclusive responsibilities
Split settings create:
main/settings/
base.py
dev.py
prod.py
test.py
Benefits: - cleaner separation - safer production config - easier onboarding - better CI/CD - easier local development - scalable architecture
Recommended Final Structure
project/
manage.py
main/
__init__.py
asgi.py
wsgi.py
urls.py
settings/
__init__.py
base.py
dev.py
prod.py
test.py
⧉
1 | |
Part 1 — Split Settings Right After Project Start
This is the easiest time to do it.
Step 1: Create Project Normally
⧉
1 | |
Default result:
main/
settings.py
urls.py
asgi.py
wsgi.py
Step 2: Convert settings.py into a Package
Inside main/:
Create directory:
⧉
1 | |
Then create:
⧉
1 2 3 4 5 | |
Step 3: Move Existing Content to base.py
Everything from original settings.py goes into: main/settings/base.py
Except for the lines that will go into dev(Step4) and prod (Step 5)
Step 4: Create dev.py
⧉
1 2 3 4 | |
Step 5: Create prod.py
⧉
1 2 3 4 5 | |
Step 6: Update manage.py
Change: main.settings
to: main.settings.dev -> when developing main.settings.prod -> when switching to production
Example:
⧉
1 2 3 4 | |
Step 7: Update wsgi.py
Usually production: main.settings.prod
Step 8: Update asgi.py
Use desired environment.
For new projects, this takes minutes.
Why Doing It Early Is The Best Approach: - No legacy imports like: - from main.settings import SOME_VAR - No deployment assumptions. - No migration complexity.
Part 2 — Splitting Settings After Project Already Exists
This is common in real projects. You started with one file. Now it’s too large and needs to be split.
Existing Project Example:
main/
settings.py
settings.py used everywhere. Maybe dozens of imports depend on it.
Migration Strategy (Safe Method)
Never "big bang" rewrite settings in one move. Use staged migration
Step 1: Create New Folder
main/settings/
Add:
__init__.py base.py dev.py prod.py
Step 2: Copy Existing settings.py to base.py
Do copy first, not move or delete.
Now both exist temporarily:
⧉
1 2 | |
Step 3: Create dev.py
⧉
1 2 3 | |
Step 4: Create prod.py
⧉
1 2 3 | |
Step 5: Update Startup Files One by One
manage.py
⧉
1 | |
wsgi.py
⧉
1 | |
asgi.py
⧉
1 | |
Step 6: Run Checks
⧉
1 2 3 | |
Step 7: Fix Old Direct Imports
Fixing old direct imports is the biggest challenge, since these can be scattered across the project
Search project for:
⧉
1 | |
Replace with:
⧉
1 | |
Then use: settings.MY_VALUE
Example:
⧉
1 2 3 4 5 6 7 8 | |
Step 8: Remove Old settings.py
Once stable and everything works as before:
delete main/settings.py
Most Common Problems During Refactor
1. Wrong Module Name
Typo:
⧉
1 | |
Correct:
⧉
1 | |
2. Missing init.py
settings need:
⧉
1 | |
3. Absolute Imports in Child Files
Wrong:
⧉
1 | |
Correct:
⧉
1 | |
4. Legacy Imports from Old Settings
Breaks startup. Use django.conf.settings
5. Production Still Uses Old Settings
Check: - Gunicorn command - Docker env vars - systemd - Heroku config - Railway/Render variables
Recommended File Responsibilities
base.py
Shared configuration: - installed apps - middleware - templates - auth - timezone - common DB defaults
dev.py
Developer environment: - DEBUG=True - sqlite or local postgres - debug toolbar - permissive hosts
prod.py
Production: - DEBUG=False - strict ALLOWED_HOSTS - secure cookies - SSL redirects - Redis - logging - CDN/static storage
test.py
Testing: - fast password hasher - in-memory email backend - temporary DB tweaks
If project is new: Split immediately to avoid future complexity, if project is expected to grow large over time.
If project exists and has: - multiple environments - multiple engineers - ~300 line settings file - deployment complexity
Split as soon as possible.
If you wait until settings.py is 1200 lines, refactoring hurts. If you split at 100 lines, it takes 15 minutes.
Join the Newsletter
Practical insights on Django, backend systems, deployment, architecture, and real-world development — delivered without noise.
Get updates when new guides, learning paths, cheat sheets, and field notes are published.
No spam. Unsubscribe anytime.
There is no third-party involved so don't worry - we won't share your details with anyone.