Django Project File Structure

Django Project File Structure

The great thing about an advanced framework like Django is that it does a lot of repetitive tasks for you. When you create a new project in Django, all of the supporting files and basic configuration are done for you so that you don’t have to spend time manually creating a bunch of individual Python files by hand. What’s more, those Python files are arranged properly to provide a basic skeleton for a functioning project in Django. In this tutorial, we’ll examine all of the files that get set up for you when creating a new project in Django.


The Outermost Project Name Directory

django outer root directory
The outer directory is the container for the Django project. It is named based on the name you provided when you ran the django-admin startproject command. In our case we used django-admin startproject myproject, therefore the name for this container directory is myproject. Some developers change the name of this folder, but likely the best-case scenario is to leave it as is. Since it does not make any difference to Django, you can rename it if you must.


The Inner Project Name Directory

django inner project folder
The inner project folder will always have the same name as the outer directory when creating a new Django project. It represents a Python package that will be used in this Django project. Again, it is likely best to leave the naming of this directory alone. We’ll see in a moment that this directory contains an __init__.py file which is what makes this directory act as a Python module or package. This is how Python works, not necessarily a Django-specific thing.


__init__.py

As mentioned above, this is to define the containing directory as a Python package. Packages are used to structure Python’s module namespace with dotted module names. For example, the module name django.utils designates a submodule named utils in a package named django. Using dotted module names means developers of multi-module packages don’t have to worry about each other’s module names.


asgi.py

"""
ASGI config for myproject project.

It exposes the ASGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
"""

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')

application = get_asgi_application()

You don’t need to worry about the asgi.py file until it comes time to deploy your Django project publically if you decide to do so. Even then, you would only work with this file if you choose the Asynchronous Server Gateway Interface as your server type.


settings.py

"""
Django settings for myproject project.

Generated by 'django-admin startproject' using Django 3.2.4.

For more information on this file, see
https://docs.djangoproject.com/en/3.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.2/ref/settings/
"""

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-i7f!50x4sy-%1qwt_bf#kv7r(9h3gynw9wu1p3wxoig$afo_^='

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

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

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'myproject.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        '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',
            ],
        },
    },
]

WSGI_APPLICATION = 'myproject.wsgi.application'


# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}


# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/

STATIC_URL = '/static/'

# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

The settings.py file is quite useful and important right away as you begin to develop a Django application. It contains many global settings for your Django project. As you add features and build your project, you will need to revisit the settings.py file to make adjustments. We can configure and fine-tune a lot of behavior via settings.py, but the defaults are perfect to get you started.


urls.py

"""myproject URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path

urlpatterns = [
    path('admin/', admin.site.urls),
]

The urls.py file is very important, since it defines how to configure the URLs for your Django Project. Django’s URL Dispatcher is quite powerful and becomes apparent as you add more pages to the Django project. It is in this urls.py file where you register the routes that point to functions in your applications. You will find yourself updating this file frequently as you build out your project.


wsgi.py

"""
WSGI config for myproject project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')

application = get_wsgi_application()

The wsgi.py file is another file that we will not touch when developing locally. You would only need to work with this file during deployment to a Web Server Gateway Interface server.


manage.py

#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys


def main():
    """Run administrative tasks."""
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)


if __name__ == '__main__':
    main()

Finally, we get to manage.py, my favorite file of all in the Django project. This file provides the developer with a ton of useful features in a command-line utility to help build, troubleshoot, and otherwise tweak your Django application. You can see all of the great things this file can do for you by typing python manage.py in the outer project name directory.

myproject $ls
manage.py*  myproject/
myproject $python manage.py

Type 'manage.py help <subcommand>' for help on a specific subcommand.

Available subcommands:

[auth]
    changepassword
    createsuperuser

[contenttypes]
    remove_stale_contenttypes

[django]
    check
    compilemessages
    createcachetable
    dbshell
    diffsettings
    dumpdata
    flush
    inspectdb
    loaddata
    makemessages
    makemigrations
    migrate
    sendtestemail
    shell
    showmigrations
    sqlflush
    sqlmigrate
    sqlsequencereset
    squashmigrations
    startapp
    startproject
    test
    testserver

[sessions]
    clearsessions

[staticfiles]
    collectstatic
    findstatic
    runserver

You do not want to change any of the code in the manage.py file. It exists so that you can use it for project-specific commands. We’ll use manage.py soon to set up a development server, manage databases, create migrations, and other important configuration-related tasks.

Learn More About Django Project File Structure