Creating a Django Project — The Right Way

Best Practice to Structure Django Project Directories, Files and Local Settings

Rai S.
6 min readFeb 8, 2023

Django is a web framework that has lots of files and folders inside it. A proper project organising can help in keeping the project DRY (Don’t Repeat Yourself) and clean. Organising a project is a must for every developer. This also helps the administrators and developers to find the proper path of files and folder. There are lots of ways for structuring directory and files of Django project.

The way I like to organize my Django Project is — Keeps all Django apps in apps folder, static files (scripts, js, CSS) in the static folder, HTML files in templates folder and images and media content in the media folder.

django_project
├── apps
│ └── app_1
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py│ ├── tests.py
│ └── views.py
├── /django_project(core)
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ └── settings.cpython-35.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
├── media
├── static
└── templates

Creating a Django Project

Create a folder where you want to keep your project. And open the directory.

mkdir my_project
cd my_project/

Within that directory create a Virtual Environment for your Django project and activate that virtual environment.

python3 -m venv env
source env/bin/activate

It may look like this – (env) user@host:~/django_project$

Now its time to install Django in your Virtual Environment.

pip3 install django

Now create a Django Project using the below command.

django-admin startproject django_project

This will create your Django project named ‘django_project’ and Django main settings folder, with the same name ‘django_project’. This is the normal way django projects are.

Alternatively, you can change the django setup folder with a name like ‘setup’ or ‘core’, only to manage your project in a better way. To do this, create a Django Project using the below command.

> django-admin startproject core

This will create your Django project named ‘core’ and Django main settings folder, with the same name ‘core’. Now rename the project name to ‘django_project’ by right clicking and selecting rename. Or by using below command. Changing the project root name from ‘core’ to ‘django_project’.

> mv core django_project

Now that you have created Django project, within the same directory you will be creating apps, media, static and templates folders.

mkdir static
mkdir media
mkdir templates
mkdir apps

Open your django_project/settings.py with your text editor/IDE by selecting it. Or open it using following command.

sudo nano django_project/settings.py

After adding the path, save and exit the file.

Creating Django Project Apps

I prefer to think of Django applications as reusable modules or components. This helps me encapsulate and decouple certain features from one another, improving re-usability and maintainability. My general approach is to bucket up specific features or feature sets into “apps”.

To create Django project apps you need to change your directory, to do that you need to go to ‘apps’ folder and once inside it, run the startapp command.

cd apps/
django-admin startapp app_1

If you will notice in your apps folder, you will find the app_1 folder inside it.

Now, that you have created app_1 app you need to register it in settings.py

To register a Django App, open your django_project/settings.py with your text editor/IDE and find the definition for the INSTALLED_APPS list.

sudo nano django_project/settings.py

Add the app name which you have created to INSTALLED_APPS list.

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',

'apps.app_1', # <--- here
]

Let me break it down, to help you better understand. apps is folder name apps where have kept apps and app_1 is the newly created app name.

Tip – I like to create urls.py for every app. It helps me to organize my routes. Just in your main project urls.py include the urls.py of your apps.

Configuring Local Settings File

Developing Django Application needs configurations and settings. Managing these configurations is a must for projects. We have to configure projects for different environments like testing, staging, production, and development. It is important to manage default and new configurations.

Django does not provide a way to have separate configurations. All project-related configurations are put in settings.py file. There are several methods to meet the above requirements, however, my favorite one is having different local settings module and everything distinct.

Open your django_project/settings.py with your text editor/IDE by selecting it. Or open it using following command.

sudo nano django_project/settings.py

Separating Django Application definition — INSTALLED_APPS

To enable apps, we need to add Apps in INSTALLED_APPS settings. Apps can be of different types like a library, third-party apps, project apps, and default apps. Everything added in INSTALLED_APPS will look confusing.

By default, INSTALLED_APPS in settings.py will look like this –

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]

To solved the above problem, I have found a good technique. We will separate the lists for default apps, third-party apps, and local apps.

To do that replace your INSTALLED_APPS with the following –

DEFAULT_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
THIRD_PARTY_APPS =[
# add apps which you install using pip
]
LOCAL_APPS =[
# add local apps which you create using startapp
]
# Application definition
INSTALLED_APPS = DEFAULT_APPS + THIRD_PARTY_APPS + LOCAL_APPS

Separating Django Database Local Settings

Projects are first created and develop in development mode, then it shifted to production mode. The projects are shifted to different environments and machines. Every environment has different credentials and settings for the database, so you need to change it every time.

To avoid code break and separate local database values, you will create a file name local_settings.py and import it in settings.py file.

Remove the database definition code from settings.py file and add it to local_settings.py

# local_settings.py
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django_shop',
'USER': 'root',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '80',
}
}

And import that local_settings.py file in settings.py file at the end –

# settings.py
# ...
# Loading from local_settings.py file
try:
from django_shop.local_settings import *
except ImportError:
pass

Changing Django Template Paths Directory

Instead of keeping all your template under the apps folder, create a separate folder and keep all apps template in that.

Create a template folder named templates at the level of the manage.py file. Now that you have created a template folder, you need to tell your Django project about that template path.

Edit TEMPLATES, add ‘DIRS’ key in TEMPLATES. Add the template path 'DIRS': [BASE_DIR + '/templates/',], in settings.py.

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR + '/templates/',], # <- here
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

Adding Static and Media Paths

For making our static and media files to serve, you need to add the path to our settings.py file. Make sure django.contrib.staticfiles is added to INSTALLED_APPS, by default it is there.

Add the following lines at the end of the file your settings.py file.

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

After adding the path, save and exit the file.

Note — Our media and static folder are at the level of manage.py file.

Also you can see full settings.py and local_settings.py files on GitHub.

Gathering Static Files

django.contrib.staticfiles provides a way of gathering static files in a single directory, so you can serve them easily. As you have set above the STATIC_ROOT path. Now once you run the collectstatic command, it will copy all static files to STATIC_ROOT Folder.

./manage.py collectstatic

It will give a message like this — 119 static files copied to 'django_project/static'.

Now you have done it. To run the project go to the main project directory and run the following command:

./manage.py runserver

Some Example that will help you –

How to use HTML file which is stored inside the templates folder.

from django.views.generic.base import TemplateView
from articles.models import Article


class HomePageView(TemplateView):
template_name = "home.html" # templates/home.html
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['latest_articles'] = Article.objects.all()[:5]
return context

How to use static files in the template which are stored in your static folder

{% load static %}
<html>
<head>
<link rel="stylesheet" href="{% static 'app.css' %}"> <!-- static/app.css -->
</head>
<body>
<h1>Sample</h1>
<script src="{% static 'app.js' %}"></script> <!-- static/app.js -->
</body>
</html>

That’s it, I hope this helps. :)

References:

--

--

Rai S.

I'm a Software Engineer and I love to write about my learning journey.