Anatomy of a Django Project
1. Creating a Django Project
With your virtual environment active and Django installed, run this command to scaffold a new project. We will call it mysite:
django-admin startproject mysite .
The dot (.) at the end is important — it tells Django to create the project files inside your current directory rather than creating a new subdirectory. Without the dot, Django creates an extra nesting level (mysite/mysite/) that trips up many beginners.
After running this command, your directory will look like this:
myproject/
│
├── manage.py ← The project's command-line toolbelt
├── venv/ ← Your virtual environment (not part of the project code)
│
└── mysite/ ← The Python package for your project configuration
├── __init__.py
├── settings.py ← All project-wide configuration lives here
├── urls.py ← The master URL routing table
├── wsgi.py ← Entry point for WSGI servers (e.g., Gunicorn)
└── asgi.py ← Entry point for ASGI servers (e.g., Daphne, Uvicorn)
2. manage.py — Your Command-Line Toolbelt
manage.py is a thin wrapper around Django’s management command system. You will use it for almost every Django operation. You should never need to edit it. Here are the most important commands you will run throughout this series:
| Command | What it does |
|---|---|
python manage.py runserver | Starts Django’s built-in development web server at http://127.0.0.1:8000/. |
python manage.py startapp | Creates a new Django app inside the project. |
python manage.py makemigrations | Detects changes to your models and generates database migration files. |
python manage.py migrate | Applies pending migration files to the database. |
python manage.py createsuperuser | Creates an admin user account. |
python manage.py shell | Opens an interactive Python shell with Django fully loaded. |
python manage.py collectstatic | Gathers all static files into one folder for production serving. |
3. settings.py — The Heart of Your Configuration
settings.py is a standard Python file that contains every configuration variable for your Django project. Open it and you will see these key settings:
# mysite/settings.py
# A long, random, cryptographic string. Django uses it to sign cookies
# and security tokens. NEVER share this or commit it to a public repository.
SECRET_KEY = 'django-insecure-...'
# When True, Django shows detailed error pages. Set to False in production.
DEBUG = True
# A list of domain names allowed to serve this site. In production,
# this prevents HTTP Host header attacks.
ALLOWED_HOSTS = []
# Lists every Django app (built-in and your own) that this project uses.
# Django only loads models, admin configurations, and templates from
# apps listed here.
INSTALLED_APPS = [
'django.contrib.admin', # The built-in admin panel
'django.contrib.auth', # User authentication system
'django.contrib.contenttypes',
'django.contrib.sessions', # Session management
'django.contrib.messages', # One-time flash messages
'django.contrib.staticfiles', # Static file serving
]
# Configures the database backend. The default is SQLite — a single file
# on disk, perfect for development. We switch to PostgreSQL for production.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Where Django looks for HTML template files.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'], # We add this line later
'APP_DIRS': True,
...
},
]
4. urls.py — The Master URL Table
This file is Django’s root routing configuration. Every URL that your site handles must trace back here. By default it contains one entry — the admin panel:
# mysite/urls.py
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
]
5. wsgi.py and asgi.py — The Server Gateway Files
WSGI (Web Server Gateway Interface, pronounced “whiskey”) and ASGI (Asynchronous Server Gateway Interface) are Python standards that define how a web server communicates with a Python web application. Think of them as an electrical adapter: the web server speaks one “language” and Python speaks another, and these files translate between them.
wsgi.py— Used by synchronous servers like Gunicorn. This is what you use for standard HTTP request-response applications. We configure this in Chapter 15 for deployment.asgi.py— Used by async servers like Uvicorn or Daphne. Required for real-time features like WebSockets (covered in Part 2).
You rarely need to edit these files directly. They exist so that production servers like Gunicorn know where to find your Django application.
6. Running the Development Server
Start the built-in development server to confirm everything is working:
python manage.py runserver
You will see output similar to:
Django version 5.0.6, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Open http://127.0.0.1:8000/ in your browser. You will see Django’s rocket ship welcome page. Your project is alive.
Important: The built-in development server (
runserver) is for development only. It handles one request at a time, restarts automatically when code changes, and is not designed for security or performance. We deploy with Gunicorn in Chapter 15.