Introduction and Foundations

Creating Your First Django Project

Creating a Django project is the first step in building web applications with Django. This guide covers project creation, initial configuration, and best practices for setting up a professional Django development environment.

Creating Your First Django Project

Creating a Django project is the first step in building web applications with Django. This guide covers project creation, initial configuration, and best practices for setting up a professional Django development environment.

Understanding Django Projects

A Django project is a collection of settings and applications for a particular website. It's the top-level container that holds:

  • Configuration settings
  • URL routing
  • Multiple Django apps
  • Deployment configurations

Think of a project as your entire website, while apps are individual features within that website.

Prerequisites

Before creating your first project, ensure you have:

  • Django installed in a virtual environment
  • Basic understanding of command line operations
  • A text editor or IDE ready for development

Verify Django Installation:

# Activate your virtual environment
source django_env/bin/activate  # macOS/Linux
django_env\Scripts\activate     # Windows

# Check Django version
python -m django --version

Creating a New Project

Step 1: Choose Your Project Location

Navigate to where you want to create your project:

# Create a directory for your Django projects
mkdir ~/django_projects
cd ~/django_projects

# Or use any directory you prefer
cd /path/to/your/workspace

Step 2: Create the Project

Use Django's startproject command:

# Basic project creation
django-admin startproject mysite

# Create project in current directory
django-admin startproject mysite .

# Create project with custom template
django-admin startproject mysite --template=https://github.com/user/template.git

Project Naming Best Practices:

  • Use lowercase letters and underscores
  • Avoid Python keywords (class, def, import)
  • Avoid built-in module names (django, test, sys)
  • Use descriptive names (blog_site, ecommerce_platform)

Step 3: Explore the Project Structure

After creation, you'll see this structure:

mysite/
├── manage.py
└── mysite/
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    ├── wsgi.py
    └── asgi.py

Let's examine each file:

manage.py

A command-line utility for interacting with your Django project:

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

if __name__ == '__main__':
    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)

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 collectstatic      # Collect static files
python manage.py shell              # Open Django shell
python manage.py test               # Run tests

settings.py

Contains all configuration for your Django project:

"""
Django settings for mysite project.

Generated by 'django-admin startproject' using Django 4.2.7.
"""

from pathlib import Path

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

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-your-secret-key-here'

# 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 = 'mysite.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 = 'mysite.wsgi.application'

# Database
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'
TIME_ZONE = 'UTC'
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

The URL dispatcher for your project:

"""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),
]

wsgi.py and asgi.py

Entry points for web servers:

WSGI (Web Server Gateway Interface):

"""
WSGI config for mysite 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/4.2/howto/deployment/wsgi/
"""

import os
from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
application = get_wsgi_application()

ASGI (Asynchronous Server Gateway Interface):

"""
ASGI config for mysite 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/4.2/howto/deployment/asgi/
"""

import os
from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
application = get_asgi_application()

Initial Project Configuration

Step 1: Navigate to Project Directory

cd mysite

Step 2: Apply Initial Migrations

Django comes with built-in apps that require database tables:

python manage.py migrate

Expected Output:

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 sessions.0001_initial... OK

Step 3: Create a Superuser

Create an admin user to access Django's admin interface:

python manage.py createsuperuser

Follow the prompts:

Username (leave blank to use 'your_username'): admin
Email address: admin@example.com
Password: 
Password (again): 
Superuser created successfully.

Step 4: Start the Development Server

python manage.py runserver

Expected Output:

Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
November 15, 2024 - 15:30:45
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.

Step 5: Test Your Project

Visit in your browser:

You should see Django's welcome page and be able to log into the admin interface.

Customizing Your Project

Environment-Specific Settings

For professional development, split your settings:

Create Settings Package

mkdir mysite/settings
touch mysite/settings/__init__.py

Move and Split Settings

mysite/settings/base.py:

"""
Base settings for mysite project.
"""
from pathlib import Path
import os

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

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ.get('SECRET_KEY', 'django-insecure-change-me')

# Application definition
DJANGO_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

THIRD_PARTY_APPS = [
    # Add third-party apps here
]

LOCAL_APPS = [
    # Add your apps here
]

INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS

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'

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',
            ],
        },
    },
]

WSGI_APPLICATION = 'mysite.wsgi.application'

# 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'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True

# Static files (CSS, JavaScript, Images)
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATICFILES_DIRS = [
    BASE_DIR / 'static',
]

# Media files
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'

# Default primary key field type
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

mysite/settings/development.py:

from .base import *

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

ALLOWED_HOSTS = ['localhost', '127.0.0.1', '0.0.0.0']

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

# Development-specific apps
INSTALLED_APPS += [
    'django_extensions',  # Provides additional management commands
]

# Email backend for development
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

# Logging configuration
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
    },
    'root': {
        'handlers': ['console'],
    },
    'loggers': {
        'django': {
            'handlers': ['console'],
            'level': 'INFO',
            'propagate': False,
        },
    },
}

mysite/settings/production.py:

from .base import *
import dj_database_url

DEBUG = False

ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com']

# Database configuration from environment variable
DATABASES = {
    'default': dj_database_url.config(
        default=os.environ.get('DATABASE_URL')
    )
}

# Security settings
SECURE_SSL_REDIRECT = True
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True
X_FRAME_OPTIONS = 'DENY'

# Email configuration
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = os.environ.get('EMAIL_HOST')
EMAIL_PORT = int(os.environ.get('EMAIL_PORT', 587))
EMAIL_USE_TLS = True
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')

Update manage.py

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

if __name__ == '__main__':
    # Use development settings by default
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings.development')
    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)

Environment Variables

Create a .env file for sensitive configuration:

# .env
SECRET_KEY=your-super-secret-key-here
DEBUG=True
DATABASE_URL=sqlite:///db.sqlite3
ALLOWED_HOSTS=localhost,127.0.0.1
EMAIL_HOST=smtp.gmail.com
EMAIL_HOST_USER=your-email@gmail.com
EMAIL_HOST_PASSWORD=your-app-password

Install python-decouple:

pip install python-decouple

Update base.py to use environment variables:

from decouple import config, Csv

SECRET_KEY = config('SECRET_KEY')
DEBUG = config('DEBUG', default=False, cast=bool)
ALLOWED_HOSTS = config('ALLOWED_HOSTS', default='', cast=Csv())

Project Directory Structure

Create a professional directory structure:

mkdir -p templates static/{css,js,images} media apps docs tests
touch templates/base.html static/css/main.css static/js/main.js

Final Structure:

mysite/
├── manage.py
├── requirements.txt
├── .env
├── .gitignore
├── README.md
├── mysite/
│   ├── __init__.py
│   ├── settings/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── development.py
│   │   └── production.py
│   ├── urls.py
│   ├── wsgi.py
│   └── asgi.py
├── apps/
│   └── __init__.py
├── templates/
│   └── base.html
├── static/
│   ├── css/
│   ├── js/
│   └── images/
├── media/
├── docs/
└── tests/

Requirements File

Create requirements.txt:

Django==4.2.7
python-decouple==3.8
Pillow==10.0.1
django-extensions==3.2.3

For development:

# requirements-dev.txt
-r requirements.txt
django-debug-toolbar==4.2.0
pytest-django==4.5.2
black==23.9.1
flake8==6.1.0

Git Configuration

Create .gitignore:

# Django
*.log
*.pot
*.pyc
__pycache__/
local_settings.py
db.sqlite3
db.sqlite3-journal
media/

# Virtual Environment
django_env/
venv/
env/

# IDE
.vscode/
.idea/
*.swp
*.swo

# Environment Variables
.env
.env.local

# OS
.DS_Store
Thumbs.db

# Static files
staticfiles/

Initialize Git:

git init
git add .
git commit -m "Initial Django project setup"

Testing Your Setup

Create a Simple View

Create mysite/views.py:

from django.http import HttpResponse
from django.shortcuts import render

def home(request):
    return HttpResponse("<h1>Welcome to My Django Site!</h1>")

def about(request):
    context = {
        'title': 'About Us',
        'message': 'This is a Django project created with best practices.'
    }
    return render(request, 'about.html', context)

Update URLs

Update mysite/urls.py:

from django.contrib import admin
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static
from . import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.home, name='home'),
    path('about/', views.about, name='about'),
]

# Serve media files during development
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Create Templates

templates/base.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}My Django Site{% endblock %}</title>
    {% load static %}
    <link rel="stylesheet" href="{% static 'css/main.css' %}">
</head>
<body>
    <header>
        <nav>
            <a href="{% url 'home' %}">Home</a>
            <a href="{% url 'about' %}">About</a>
            <a href="{% url 'admin:index' %}">Admin</a>
        </nav>
    </header>
    
    <main>
        {% block content %}{% endblock %}
    </main>
    
    <footer>
        <p>&copy; 2024 My Django Site</p>
    </footer>
</body>
</html>

templates/about.html:

{% extends 'base.html' %}

{% block title %}{{ title }} - {{ block.super }}{% endblock %}

{% block content %}
    <h1>{{ title }}</h1>
    <p>{{ message }}</p>
{% endblock %}

Add Basic Styling

static/css/main.css:

body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
    line-height: 1.6;
}

header {
    background: #333;
    color: white;
    padding: 1rem;
}

nav a {
    color: white;
    text-decoration: none;
    margin-right: 1rem;
}

nav a:hover {
    text-decoration: underline;
}

main {
    padding: 2rem;
    min-height: 70vh;
}

footer {
    background: #333;
    color: white;
    text-align: center;
    padding: 1rem;
}

Common Issues and Solutions

Issue 1: Port Already in Use

Problem: Error: That port is already in use.Solution:

# Use different port
python manage.py runserver 8080

# Or kill process using port 8000
lsof -ti:8000 | xargs kill -9  # macOS/Linux
netstat -ano | findstr :8000   # Windows

Issue 2: Settings Module Not Found

Problem: ModuleNotFoundError: No module named 'mysite.settings'Solution:

# Ensure you're in the correct directory
cd mysite

# Check DJANGO_SETTINGS_MODULE
echo $DJANGO_SETTINGS_MODULE

# Set explicitly if needed
export DJANGO_SETTINGS_MODULE=mysite.settings.development

Issue 3: Database Errors

Problem: Database-related errors during migration Solution:

# Delete database and start fresh
rm db.sqlite3

# Recreate migrations
python manage.py makemigrations
python manage.py migrate

Issue 4: Static Files Not Loading

Problem: CSS/JS files not loading in development Solution:

# In settings.py, ensure:
STATIC_URL = '/static/'
STATICFILES_DIRS = [BASE_DIR / 'static']

# In urls.py, add:
from django.conf import settings
from django.conf.urls.static import static

if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

Next Steps

Your Django project is now set up with professional best practices. Next steps include:

  1. Create your first app - Add specific functionality
  2. Set up a database - Configure PostgreSQL or MySQL
  3. Create models - Define your data structure
  4. Build views and templates - Create user interfaces
  5. Add authentication - User registration and login
  6. Deploy your project - Make it available online

Best Practices Summary

Use virtual environments for dependency isolation ✅ Split settings by environment (development/production) ✅ Use environment variables for sensitive data ✅ Create proper directory structure for scalability ✅ Version control with Git from the start ✅ Document your setup with README files ✅ Pin dependencies in requirements.txt ✅ Follow naming conventions for consistency

Your Django project foundation is now solid and ready for building amazing web applications!