Django Project Structure: Understanding Files and Folders

Django project structure follows a well-defined organizational pattern that separates concerns, promotes code reusability, and maintains scalability as applications grow. Understanding the purpose and functionality of each generated file and directory is fundamental to effective Django development enabling developers to navigate codebases confidently, modify configurations appropriately, and implement features following framework conventions. When Django creates a new project, it generates a root directory containing the management script and an inner package directory housing core configuration files including settings, URL routing, and deployment configurations. This hierarchical structure distinguishes project-level configurations from application-specific code facilitating modular development where individual apps can be developed independently and potentially reused across different projects. Mastering Django's project anatomy empowers developers to customize framework behavior, organize large codebases efficiently, and follow best practices that align with Django's philosophy of convention over configuration for rapid development without sacrificing flexibility.
Project Structure Overview
Django projects consist of two main directory levels: the outer project root directory serving as a container for the entire project, and the inner project package directory containing core configuration files. The root directory's name can be changed without affecting project functionality as Django references the inner package for imports and configurations. Inside the root directory, manage.py provides the command-line interface for project management tasks while the inner package directory shares the project name and functions as a Python package enabling imports throughout the application. This dual-directory structure separates project management utilities from configuration code maintaining clean organization. Understanding this distinction helps developers navigate projects, set up version control correctly by including the inner package while potentially excluding virtual environments and databases, and configure deployment environments where the outer directory might be named differently for organizational purposes.
# Django project structure after creation
myproject/ # Root project directory (can be renamed)
βββ manage.py # Django's command-line utility
βββ db.sqlite3 # SQLite database (after migrations)
βββ myproject/ # Inner project package (Python package)
β βββ __init__.py # Makes directory a Python package
β βββ settings.py # Project configuration settings
β βββ urls.py # URL routing declarations
β βββ asgi.py # ASGI deployment configuration
β βββ wsgi.py # WSGI deployment configuration
βββ venv/ # Virtual environment (not in version control)
βββ static/ # Static files directory (CSS, JS, images)
βββ media/ # User-uploaded files
βββ templates/ # Project-level templates
βββ requirements.txt # Python dependencies
# After creating apps, structure expands:
myproject/
βββ manage.py
βββ myproject/
βββ app1/ # First Django app
βββ app2/ # Second Django app
βββ app3/ # Third Django appmanage.py - Command Line Utility
The manage.py file serves as Django's primary command-line interface providing access to administrative tasks, development server management, database operations, and custom command execution. This Python script wraps django-admin functionality while automatically setting the DJANGO_SETTINGS_MODULE environment variable pointing to your project's settings file. Every Django management command executes through manage.py including runserver for starting the development server, migrate for applying database migrations, createsuperuser for creating admin users, and startapp for generating new applications. The file rarely requires modification as it functions as a thin wrapper around Django's core management utilities. However, understanding its contents reveals how Django initializes the project environment and locates configuration settings. Developers interact with manage.py constantly throughout development making it the most frequently executed file in Django projects despite its simplicity and typically unchanged state.
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
# Points to project settings module
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 command passed as arguments
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
# Common manage.py commands:
# python manage.py runserver - Start development server
# python manage.py migrate - Apply database migrations
# python manage.py makemigrations - Create new migrations
# python manage.py createsuperuser - Create admin user
# python manage.py shell - Open Django shell
# python manage.py test - Run tests
# python manage.py collectstatic - Gather static files
# python manage.py startapp appname - Create new appsettings.py - Project Configuration
The settings.py file contains all project configuration including database connections, installed applications, middleware, template engines, static file locations, security settings, and internationalization options. This centralized configuration file follows Python syntax allowing conditional logic, environment variable imports, and calculated values rather than static configuration formats. Key settings include SECRET_KEY for cryptographic signing, DEBUG for development mode toggle, ALLOWED_HOSTS for permitted server hostnames, INSTALLED_APPS listing active Django applications and third-party packages, MIDDLEWARE defining request/response processing layers, DATABASES configuring database connections, and STATIC_URL specifying static file serving paths. Understanding settings organization enables customization of Django's behavior without modifying framework code following the principle of configuration over code modification. Proper settings management includes separating development and production configurations, securing sensitive values through environment variables, and documenting custom settings for team collaboration.
# settings.py - Core Django configuration
from pathlib import Path
# Build paths inside the project
BASE_DIR = Path(__file__).resolve().parent.parent
# Security settings
SECRET_KEY = 'django-insecure-key-change-in-production'
DEBUG = True # Set to False in production
ALLOWED_HOSTS = [] # Add domains in production
# Application definition
INSTALLED_APPS = [
'django.contrib.admin', # Admin interface
'django.contrib.auth', # Authentication
'django.contrib.contenttypes',# Content type framework
'django.contrib.sessions', # Session framework
'django.contrib.messages', # Messaging framework
'django.contrib.staticfiles', # Static file management
# Add your apps here
# 'myapp',
]
# Middleware
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',
]
# URL configuration
ROOT_URLCONF = 'myproject.urls'
# Templates
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'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',
],
},
},
]
# Database
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Static files
STATIC_URL = 'static/'
STATICFILES_DIRS = [BASE_DIR / 'static']
STATIC_ROOT = BASE_DIR / 'staticfiles'
# Media files
MEDIA_URL = 'media/'
MEDIA_ROOT = BASE_DIR / 'media'
# Internationalization
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Default primary key field type
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'urls.py - URL Routing Configuration
The urls.py file defines URL patterns mapping web addresses to view functions or classes establishing the routing mechanism for handling HTTP requests. Django's URL dispatcher compares requested URLs against defined patterns in order executing the first matching pattern's associated view. The urlpatterns list contains path() or re_path() function calls specifying URL patterns, view references, optional names for reverse URL resolution, and pattern parameters extracted from URLs and passed to views. Project-level urls.py typically includes routes to the admin interface and includes URL configurations from individual applications using include() function enabling modular URL organization. Understanding URL configuration enables creating clean, meaningful URLs following RESTful conventions, implementing URL parameters for dynamic content, organizing routes logically, and using named URLs for maintainable template and view code that doesn't hardcode paths.
# urls.py - Project URL configuration
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# Admin interface
path('admin/', admin.site.urls),
# Include app URLs
# path('blog/', include('blog.urls')),
# path('api/', include('api.urls')),
# path('accounts/', include('accounts.urls')),
]
# Serve media files in development
if settings.DEBUG:
urlpatterns += static(
settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT
)
# URL pattern examples:
# path('', views.home, name='home') # Homepage
# path('about/', views.about, name='about') # Static page
# path('post/<int:id>/', views.post_detail) # With parameter
# path('post/<slug:slug>/', views.post_by_slug) # Slug parameter
# re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive) # Regexwsgi.py and asgi.py - Deployment Configuration
Django generates two deployment configuration files: wsgi.py for traditional synchronous web servers and asgi.py for asynchronous server gateway interface supporting WebSockets and real-time features. WSGI (Web Server Gateway Interface) represents the standard Python interface for synchronous web applications and servers enabling deployment with Gunicorn, uWSGI, or Apache mod_wsgi in production environments. ASGI (Asynchronous Server Gateway Interface) extends WSGI to support asynchronous Python applications enabling WebSocket connections, HTTP/2, and long-polling for real-time communication features through servers like Daphne or Uvicorn. Both files expose a callable application object that web servers use to communicate with Django providing the bridge between web server software and Django application code. Most traditional Django applications use WSGI for deployment, while applications leveraging Django Channels for chat, notifications, or real-time updates require ASGI. Understanding these files becomes important during production deployment when configuring web servers and application servers to serve Django applications.
# wsgi.py - WSGI configuration for deployment
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
application = get_wsgi_application()
# Used with WSGI servers:
# gunicorn myproject.wsgi:application
# uwsgi --http :8000 --module myproject.wsgi
# ============================================
# asgi.py - ASGI configuration for async deployment
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
application = get_asgi_application()
# For Django Channels (WebSockets):
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
# import myapp.routing
# application = ProtocolTypeRouter({
# 'http': get_asgi_application(),
# 'websocket': AuthMiddlewareStack(
# URLRouter(
# myapp.routing.websocket_urlpatterns
# )
# ),
# })
# Used with ASGI servers:
# daphne myproject.asgi:application
# uvicorn myproject.asgi:application__init__.py - Python Package Marker
The __init__.py file designates directories as Python packages enabling imports from those directories. In Django projects, the inner project directory contains __init__.py making it a Python package and allowing import statements like 'from myproject.settings import DATABASES' throughout the codebase. Typically this file remains empty serving solely as a package marker, though it can contain package initialization code, submodule imports for convenience, or version information for reusable packages. Django automatically creates this file in project and app directories ensuring proper Python package structure. While Python 3.3 introduced namespace packages reducing __init__.py requirement, Django maintains explicit package markers for compatibility and clarity. Understanding __init__.py importance prevents accidental deletion and enables package-level imports or initialization code when needed for advanced use cases like dynamic app loading or package-wide configuration.
db.sqlite3 - Development Database
Django creates db.sqlite3 file when running initial migrations providing a file-based SQLite database perfect for development without requiring database server installation or configuration. SQLite offers zero-configuration setup, making it ideal for learning Django, rapid prototyping, and local development environments. The database file contains all tables, data, indexes, and schema defined by Django models and migrations including built-in tables for authentication, sessions, and admin interface. While convenient for development, SQLite has limitations for production use including limited concurrent write operations, no network access, and reduced performance with large datasets. Production applications typically use PostgreSQL, MySQL, or MariaDB database servers providing superior performance, scalability, and concurrent access handling. The db.sqlite3 file should be excluded from version control as it contains local development data and can be recreated by running migrations on a fresh Django installation.
Additional Project Directories
Django projects commonly include additional directories for organizing static files, media uploads, and templates. The static directory stores CSS stylesheets, JavaScript files, images, and other assets served directly to browsers without processing. Configuring STATICFILES_DIRS in settings tells Django where to find static files during development, while STATIC_ROOT defines where collectstatic management command gathers files for production serving. The media directory stores user-uploaded files like profile pictures, documents, or attachments with MEDIA_ROOT and MEDIA_URL settings controlling storage location and URL serving path. Templates directory holds project-level HTML templates shared across applications with apps maintaining their own template subdirectories for app-specific templates. Creating these directories follows Django conventions enabling predictable file organization and simplifying configuration. Understanding static versus media file distinction prevents security issues as media files come from untrusted user uploads requiring different handling than developer-controlled static assets.
# Project directory structure with common additions
myproject/
βββ manage.py
βββ db.sqlite3
βββ myproject/
β βββ __init__.py
β βββ settings.py
β βββ urls.py
β βββ asgi.py
β βββ wsgi.py
βββ static/ # Project-level static files
β βββ css/
β β βββ style.css
β βββ js/
β β βββ main.js
β βββ images/
β βββ logo.png
βββ media/ # User-uploaded files
β βββ uploads/
β βββ profile_pics/
βββ templates/ # Project-level templates
β βββ base.html
β βββ navbar.html
β βββ footer.html
βββ locale/ # Translation files
βββ logs/ # Application logs
βββ venv/ # Virtual environment
βββ .env # Environment variables
βββ .gitignore # Git ignore file
βββ requirements.txt # Dependencies
# .gitignore example
# *.pyc
# __pycache__/
# db.sqlite3
# /venv/
# /staticfiles/
# /media/
# .env
# *.logDjango Apps Structure
Django applications represent self-contained components handling specific functionality within projects like blog, authentication, API, or e-commerce features. Each app contains its own models, views, templates, static files, and URL configurations promoting modularity and reusability across different projects. Running python manage.py startapp creates app directories containing migrations folder for database schema changes, admin.py for admin interface registration, apps.py for app configuration, models.py for database models, tests.py for test cases, and views.py for view functions or classes. Apps must be registered in INSTALLED_APPS setting to be recognized by Django enabling model detection, template loading, and migration discovery. Well-designed apps focus on single concerns following Django's philosophy of reusable components that can be plugged into multiple projects. Understanding app structure enables organizing large projects into manageable modules, sharing functionality between projects, and following Django best practices for scalable application architecture.
# Create Django app
python manage.py startapp blog
# Generated app structure
blog/
βββ __init__.py # Package marker
βββ admin.py # Admin interface configuration
βββ apps.py # App configuration
βββ models.py # Database models
βββ tests.py # Test cases
βββ views.py # View functions/classes
βββ migrations/ # Database migrations
β βββ __init__.py
βββ templates/ # App-specific templates (create manually)
β βββ blog/
β βββ post_list.html
β βββ post_detail.html
βββ static/ # App-specific static files (create manually)
β βββ blog/
β βββ css/
β βββ js/
βββ urls.py # App URL configuration (create manually)
# Register app in settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog', # Add your app here
]Project Organization Best Practices
Effective Django project organization follows conventions promoting maintainability, scalability, and team collaboration. Separating settings into multiple files for development, staging, and production environments enables environment-specific configurations while maintaining a base settings file with shared configurations. Using environment variables for sensitive information like SECRET_KEY, database credentials, and API keys prevents accidental credential exposure in version control. Creating dedicated directories for templates, static files, and media uploads maintains clear separation of concerns. Documenting project structure in README files helps new team members understand organization and locate specific functionality. Following consistent naming conventions for apps, models, and views improves code readability. Keeping apps focused on single responsibilities enables reusability and simplifies testing. Regularly updating requirements.txt ensures dependency documentation accuracy. Implementing proper .gitignore prevents committing generated files, databases, and virtual environments to version control. These practices scale from small projects to enterprise applications maintaining code quality and development efficiency throughout project lifecycle.
$ share --platform
$ cat /comments/ (0)
$ cat /comments/
// No comments found. Be the first!


