First Django Project
This chapter will guide you through creating your first Django project, understanding the basic structure of a Django project, and running your first web application.
Creating a Django Project
Using django-admin to Create a Project
# Make sure the virtual environment is activated
(venv) $ django-admin startproject mysite
# View the created project structure
cd mysite
tree . # Linux/macOS
# or
dir /s # WindowsProject Structure Analysis
mysite/
├── manage.py # Django project management script
└── mysite/ # Project configuration package
├── __init__.py # Python package identifier
├── settings.py # Project settings file
├── urls.py # URL configuration file
├── asgi.py # ASGI configuration file
└── wsgi.py # WSGI configuration filemanage.py Detailed Explanation
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
# Set Django settings module
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.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()Main uses of manage.py:
- Run development server
- Create applications
- Execute database migrations
- Create superuser
- Collect static files
settings.py Detailed Explanation
# mysite/settings.py
"""
Django settings for mysite project.
Generated by 'django-admin startproject' using Django 4.2.7.
"""
from pathlib import Path
# Project root directory
BASE_DIR = Path(__file__).resolve().parent.parent
# Security key - should be kept secret in production
SECRET_KEY = 'django-insecure-your-secret-key-here'
# Debug mode - should be set to False in production
DEBUG = True
# List of allowed hosts
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin', # Admin interface
'django.contrib.auth', # Authentication system
'django.contrib.contenttypes', # Content types framework
'django.contrib.sessions', # Session framework
'django.contrib.messages', # Message framework
'django.contrib.staticfiles', # Static files management
]
# Middleware configuration
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 = 'mysite.urls'
# Template configuration
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
WSGI_APPLICATION = 'mysite.wsgi.application'
# Database configuration
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
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
LANGUAGE_CODE = 'en-us' # English
TIME_ZONE = 'UTC' # UTC timezone
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
STATIC_URL = 'static/'
# Default primary key field type
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'urls.py Detailed Explanation
# mysite/urls.py
"""mysite URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.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),
]Running Development Server
Starting the Server
# In the project root directory (directory containing manage.py)
python manage.py runserver
# Output information
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
December 15, 2023 - 10:30:00
Django version 4.2.7, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.Accessing the Website
Open your browser and visit http://127.0.0.1:8000/, you should see the Django welcome page:
<!-- Django welcome page content -->
The install worked successfully! Congratulations!
You are seeing this message because this Django installation is working correctly.
Next, start your first app by running python manage.py startapp [app_label].Custom Server Configuration
# Specify port
python manage.py runserver 8080
# Specify IP and port
python manage.py runserver 0.0.0.0:8000
# Use different settings file
python manage.py runserver --settings=mysite.settings_devDatabase Initialization
Applying Initial Migrations
# Apply database migrations
python manage.py migrate
# Output information
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OKCreating a Superuser
# Create admin account
python manage.py createsuperuser
# Enter information as prompted
Username (leave blank to use 'yourname'): admin
Email address: admin@example.com
Password:
Password (again):
Superuser created successfully.Accessing Admin Interface
Visit http://127.0.0.1:8000/admin/ and log in using the superuser account you just created.
Creating Your First App
Django Project vs App
Project
├── App 1 (App) - Blog functionality
├── App 2 (App) - User management
├── App 3 (App) - Comment system
└── Project configurationProject: Container for the entire website App: Python package that implements specific functionality
Creating an App
# Create an app named polls
python manage.py startapp polls
# View app structure
tree polls/ # Linux/macOSApp Structure Analysis
polls/
├── __init__.py # Python package identifier
├── admin.py # Admin interface configuration
├── apps.py # App configuration
├── migrations/ # Database migration files
│ └── __init__.py
├── models.py # Data models
├── tests.py # Test files
└── views.py # View functionsApp Files Detailed Explanation
apps.py - App Configuration
# polls/apps.py
from django.apps import AppConfig
class PollsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'polls'
verbose_name = 'Polls App' # Display name in admin interfacemodels.py - Data Models
# polls/models.py
from django.db import models
# Create your models here.views.py - View Functions
# polls/views.py
from django.shortcuts import render
# Create your views here.admin.py - Admin Interface
# polls/admin.py
from django.contrib import admin
# Register your models here.Writing Your First View
Creating View Functions
# polls/views.py
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You're at the polls index.")
def detail(request, question_id):
return HttpResponse(f"You're looking at question {question_id}.")
def results(request, question_id):
response = "You're looking at the results of question %s."
return HttpResponse(response % question_id)
def vote(request, question_id):
return HttpResponse(f"You're voting on question {question_id}.")Configuring URL Routing
1. Create App URL Configuration
# polls/urls.py (new file)
from django.urls import path
from . import views
urlpatterns = [
# ex: /polls/
path('', views.index, name='index'),
# ex: /polls/5/
path('<int:question_id>/', views.detail, name='detail'),
# ex: /polls/5/results/
path('<int:question_id>/results/', views.results, name='results'),
# ex: /polls/5/vote/
path('<int:question_id>/vote/', views.vote, name='vote'),
]2. Include App URLs in Project URL Configuration
# mysite/urls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls),
]Registering the App
# mysite/settings.py
INSTALLED_APPS = [
'polls.apps.PollsConfig', # Add polls app
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]Testing Views
# Start development server
python manage.py runserver
# Visit these URLs to test
http://127.0.0.1:8000/polls/
http://127.0.0.1:8000/polls/34/
http://127.0.0.1:8000/polls/34/results/
http://127.0.0.1:8000/polls/34/vote/URL Configuration Details
URL Pattern Syntax
from django.urls import path, re_path
from . import views
urlpatterns = [
# Basic path
path('', views.index),
# Path with parameters
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<slug:slug>/', views.article_detail),
# Regex path
re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
# Optional parameters
path('blog/', views.blog_index),
path('blog/page/<int:num>/', views.blog_index),
]Path Converters
# Django built-in path converters
str # Matches any non-empty string except '/'
int # Matches positive integers, including 0
slug # Matches letters, numbers, hyphens, underscores
uuid # Matches formatted UUID
path # Matches any non-empty string, including path separator '/'
# Usage examples
urlpatterns = [
path('articles/<int:year>/', views.year_archive),
path('articles/<str:title>/', views.article_detail),
path('users/<uuid:user_id>/', views.user_profile),
path('files/<path:file_path>/', views.file_download),
]Custom Path Converters
# converters.py
class FourDigitYearConverter:
regex = '[0-9]{4}'
def to_python(self, value):
return int(value)
def to_url(self, value):
return '%04d' % value
# urls.py
from django.urls import path, register_converter
from . import views, converters
register_converter(converters.FourDigitYearConverter, 'yyyy')
urlpatterns = [
path('articles/<yyyy:year>/', views.year_archive),
]URL Naming and Reverse Resolution
# urls.py
from django.urls import path
from . import views
app_name = 'polls' # App namespace
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
path('<int:question_id>/vote/', views.vote, name='vote'),
]# Use in views
from django.urls import reverse
from django.http import HttpResponseRedirect
def vote(request, question_id):
# ... voting logic ...
return HttpResponseRedirect(reverse('polls:results', args=(question_id,)))<!-- Use in templates -->
<a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a>Project Configuration Optimization
Environment Variable Configuration
# settings.py
import os
from pathlib import Path
# Read configuration from environment variables
DEBUG = os.environ.get('DEBUG', 'False').lower() == 'true'
SECRET_KEY = os.environ.get('SECRET_KEY', 'your-default-secret-key')
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost,127.0.0.1').split(',')
# Database configuration
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# If DATABASE_URL environment variable is set, use it
DATABASE_URL = os.environ.get('DATABASE_URL')
if DATABASE_URL:
import dj_database_url
DATABASES['default'] = dj_database_url.parse(DATABASE_URL)Separate Configuration Files
mysite/
├── settings/
│ ├── __init__.py
│ ├── base.py # Base configuration
│ ├── development.py # Development environment configuration
│ ├── production.py # Production environment configuration
│ └── testing.py # Testing environment configuration# settings/base.py
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent.parent
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls.apps.PollsConfig',
]
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 = 'mysite.urls'
WSGI_APPLICATION = 'mysite.wsgi.application'
# ... other common configurations# settings/development.py
from .base import *
DEBUG = True
ALLOWED_HOSTS = ['localhost', '127.0.0.1']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Development tools
INSTALLED_APPS += [
'debug_toolbar',
'django_extensions',
]
MIDDLEWARE += [
'debug_toolbar.middleware.DebugToolbarMiddleware',
]
INTERNAL_IPS = ['127.0.0.1']# settings/production.py
from .base import *
import os
DEBUG = False
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',')
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME'),
'USER': os.environ.get('DB_USER'),
'PASSWORD': os.environ.get('DB_PASSWORD'),
'HOST': os.environ.get('DB_HOST', 'localhost'),
'PORT': os.environ.get('DB_PORT', '5432'),
}
}
# Security configuration
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
X_FRAME_OPTIONS = 'DENY'Using Different Configurations
# Development environment
python manage.py runserver --settings=mysite.settings.development
# Production environment
python manage.py migrate --settings=mysite.settings.production
# Or set environment variable
export DJANGO_SETTINGS_MODULE=mysite.settings.development
python manage.py runserverCommon Management Commands
Project Management Commands
# Create project
django-admin startproject mysite
# Create app
python manage.py startapp myapp
# Run development server
python manage.py runserver
python manage.py runserver 8080
python manage.py runserver 0.0.0.0:8000
# Check project
python manage.py check
python manage.py check --deploy # Deployment checkDatabase Management Commands
# Create migration files
python manage.py makemigrations
python manage.py makemigrations myapp
# Apply migrations
python manage.py migrate
python manage.py migrate myapp
# View migration status
python manage.py showmigrations
# View SQL statements
python manage.py sqlmigrate myapp 0001User Management Commands
# Create superuser
python manage.py createsuperuser
# Change user password
python manage.py changepassword usernameOther Useful Commands
# Collect static files
python manage.py collectstatic
# Clear sessions
python manage.py clearsessions
# Enter Django shell
python manage.py shell
# Run tests
python manage.py test
python manage.py test myapp
# Generate secret key
python manage.py shell -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"Project Deployment Preparation
Production Environment Checklist
# Security check
python manage.py check --deploy
# Common check items
SECURITY_WARNING = [
'DEBUG = False',
'SECRET_KEY must not be exposed',
'ALLOWED_HOSTS must be set',
'HTTPS configuration',
'CSRF protection',
'XSS protection',
]requirements.txt
# Generate dependencies file
pip freeze > requirements.txt
# requirements.txt content example
Django==4.2.7
psycopg2-binary==2.9.7
gunicorn==21.2.0
whitenoise==6.6.0
python-decouple==3.8Static Files Configuration
# settings.py
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATICFILES_DIRS = [
BASE_DIR / 'static',
]
# Use WhiteNoise for static files
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', # Add this line
# ... other middleware
]
# Static files compression
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'Chapter Summary
This chapter covered creating your first Django project in detail:
Key Points:
- Project Creation: Use django-admin startproject to create a project
- Project Structure: Understand Django's file organization
- App Creation: Use manage.py startapp to create apps
- URL Configuration: Set up URL routing and view mapping
- Development Server: Run and test Django applications
Important Concepts:
- Project vs App: Project is the container, app is the functional module
- MVT Architecture: Model-View-Template design pattern
- URL Routing: Map URLs to view functions
- Configuration Management: Use settings.py to manage project configuration
Best Practices:
- Create separate apps for each feature
- Use meaningful URL patterns and names
- Separate configuration files for different environments
- Use environment variables to manage sensitive information
- Follow Django project structure conventions
Development Workflow:
- Create project and app
- Configure URL routing
- Write view functions
- Test functionality
- Optimize configuration
In the next chapter, we will dive deeper into Django's basic concepts, including settings, middleware, app configuration, and other core knowledge.