When starting a new Django project I've found myself tweaking the default project structure to make it more maintainable and organized. Here's my preferred layout and the small adjustments needed to make it work.
The default Django layout works fine, but I prefer using a src
directory to cleanly separate the Django application code from project configuration files (pyproject.toml
, README.md
, etc.).
Why I Prefer This Structure
I make a few organizational changes that help keep larger projects maintainable:
- Rename the project directory to
config
- This makes it immediately clear that this directory contains configuration rather than application logic - Split settings and URLs into subdirectories -
config/settings/
andconfig/urls/
allow for clean environment-specific configurations (local, staging, production) - Create a dedicated
apps
directory - This keeps all your Django applications organized in one place, separate from configuration
Required Configuration Changes
This structure requires a few small configuration changes to work properly:
1. Tell Django where your Settings module is
Django needs to know the new path to your settings file:
export DJANGO_SETTINGS_MODULE="config.settings.local"
2. Adjust BASE_DIR Path in your Settings Module
You'll need to add an additional .parent
to the BASE_DIR
statement in your settings
module since the config/settings
directory is now nested one level deeper:
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent.parent
3. Add Apps Directory to Python Path
Finally, also in your settings
module add the apps
directory to your Python path so Django can find your applications:
# Add apps directory to Python path
sys.path.insert(0, os.path.join(BASE_DIR, "apps"))
Example Directory Structure
.
├── Justfile
├── pyproject.toml
├── README.md
├── src
│ └── scrm
│ ├── __init__.py
│ ├── apps
│ │ ├── __init__.py
│ │ ├── mycoolapp
│ │ │ ├── __init__.py
│ │ │ ├── admin.py
│ │ │ ├── apps.py
│ │ │ ├── migrations
│ │ │ ├── models.py
│ │ │ ├── templates
│ │ │ │ └── mycoolapp
│ │ │ │ ├── base.html
│ │ │ │ ├── news.html
│ │ │ │ ├── pagination_footer.html
│ │ │ ├── tests.py
│ │ │ ├── urls.py
│ │ │ └── views.py
│ ├── config
│ │ ├── __init__.py
│ │ ├── asgi.py
│ │ ├── settings
│ │ │ ├── __init__.py
│ │ │ ├── default.py
│ │ │ └── local.py
│ │ ├── urls
│ │ │ ├── __init__.py
│ │ │ ├── default.py
│ │ │ └── local.py
│ │ └── wsgi.py
│ ├── db.sqlite3
│ └── manage.py
└── uv.lock