Rohan Yeole - Homepage Rohan Yeole

Best Practices for Structuring a Django Project

By Rohan Yeole
Table of Contents

In this guide, I'll show you how to structure Django project using a clean, scalable Django boilerplate I’ve developed, following industry best practices. 

A well-structured Django project not only accelerates development but also ensures maintainability and scalability. 

Whether you're just building your first Django website  or refining an existing setup, this guide will help you build Django projects like a pro.

Overview

We'll cover the following:

  • Virtual Environments
  • Creating the Project
  • Managing Requirements
  • Settings Management
  • App Organization
  • Common Utilities (Makefile Shortcuts)

Use a Virtual Environment (VE)

Virtual environments keep your project dependencies isolated, avoiding version conflicts and global pollution.

Why It Matters

  • Prevents conflicts with global packages
  • Avoids permission issues
  • Keeps each project’s dependencies organized

Create & Activate VE

python -m venv .venv --prompt django-first
source .venv/bin/activate
pip install "Django~=5.0.0"
On Ubuntu, install python3-venv via apt if not available.

Check out: How to setup Django with a virtual environment for 

Creating the Django Project

A common beginner mistake is creating unnecessary nested folders.

Common Structure (Not Ideal)

django-admin startproject djangofirst
Results in:
Django_First/
└── djangofirst/
├── djangofirst/
└── manage.py
Recommended: Use config/ for Settings
django-admin startproject config .
Produces:
Django_First/
├── config/
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
This separates configuration logic (config) from the root directory, keeping things clean.

If you want to add search functionality to your Django project, here's an step-by-step guide on how to implement search in Django.

Managing Requirements

Most developers only use a single requirements.txt, which is fine for small projects. But for scalable apps, separate your environments.

Best Practice

Create a requirements/ folder:

requirements/
├── base.txt
└── dev.txt
base.txt
Django~=5.0
django-environ==0.11.2
dev.txt
-r base.txt
ipython==8.18.1
django-extensions==3.2.3
Use pip install -r requirements/dev.txt to install all development dependencies.

Splitting Settings for Environments

The default settings.py becomes hard to manage as your project grows. Instead, split settings by environment.

Directory Structure

config/
└── settings/
├── base.py
└── dev.py
base.py

Defines shared settings:

BASE_DIR = Path(__file__).resolve().parent.parent.parent

INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
# ...
]

MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
# ...
]

ROOT_URLCONF = "config.urls"
WSGI_APPLICATION = "config.wsgi.application"
dev.py

Environment-specific overrides:

import environ
from .base import *

env = environ.Env(DEBUG=(bool, True))
environ.Env.read_env(str(BASE_DIR / ".env"))

SECRET_KEY = env("SECRET_KEY")
DEBUG = env.bool("DEBUG", default=True)
ALLOWED_HOSTS = ["*"]

INSTALLED_APPS += ["django_extensions"]

DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
}
Keep secrets like SECRET_KEY and database credentials in a .env file.

Organizing Django Apps

Many devs put apps directly in the root directory, cluttering the workspace.

Best Practice: Use an apps/ Folder

mkdir apps
cd apps
python3 ../manage.py startapp your_app
Bonus: Core App for Shared Models

Use a core app to house common logic.

Example: apps/core/abstracts/models.py

from django.db import models

class CreatedModifiedAbstract(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)

class Meta:
abstract = True
Now, any model can inherit from CreatedModifiedAbstract.

Developer Efficiency with Makefile

Long commands slow you down. Use a Makefile for shortcuts.

Sample Makefile

dev-start:
python manage.py runserver --settings=config.settings.dev

dev-install:
pip install -r requirements/dev.txt

dev-startapp:
cd apps && python3 ../manage.py startapp $(app) --settings=config.settings.dev

dev-makemigrations:
python manage.py makemigrations --settings=config.settings.dev

dev-shell:
python manage.py shell --settings=config.settings.dev
Usage:
make dev-start
make dev-install
make dev-startapp app=blog
Final Project Structure
Django_First/
├── apps/
│ └── core/
│ └── abstracts/
│ └── models.py
├── config/
│ ├── settings/
│ │ ├── base.py
│ │ └── dev.py
│ ├── urls.py
│ └── wsgi.py
├── requirements/
│ ├── base.txt
│ └── dev.txt
├── manage.py
└── Makefile
Conclusion

Django is incredibly powerful, but many developers struggle with messy project structures that limit scalability. With this structured boilerplate:

  • Your project remains clean and maintainable
  • You can switch between dev, staging, and production environments easily
  • Your development process becomes significantly more productive

Are you ready to take your Django project further? Here's helpful next steps: