Project setup

Django is a batteries-included web framework: routing, an ORM, templates, forms, an admin and a security layer come in the box. This lesson gets a project running the way a team would actually start one.

Install into a virtual environment

Django 5.1 runs on Python 3.10 to 3.13. Always use a virtual environment so each project keeps its own versions.

python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install "django~=5.1" mysqlclient python-dotenv
django-admin startproject config .
python manage.py startapp shop
python manage.py migrate
python manage.py runserver

The trailing dot in startproject config . matters: it puts manage.py in the current folder instead of nesting another directory. Freeze what you installed with pip freeze > requirements.txt before you write any code.

What you just created

manage.py              # command-line entry point
config/
    settings.py        # all configuration
    urls.py            # the project-wide URL map
    wsgi.py / asgi.py  # the server entry points
shop/
    models.py          # data
    views.py           # logic
    admin.py           # admin registration
    migrations/        # generated schema changes

Django calls its pattern MTV: Models hold data, Templates render HTML, Views contain the logic that joins them. The URL map decides which view handles which request.

Wire the app in

In config/settings.py add your app and a project-level templates folder:

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

TEMPLATES[0]["DIRS"] = [BASE_DIR / "templates"]

TIME_ZONE = "Asia/Kolkata"
USE_TZ = True

Keeping USE_TZ = True stores timestamps in UTC and renders them in IST — do not turn it off to "fix" times.

Settings that differ per machine

Never commit a secret. Read anything environment-specific from the environment:

import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
DEBUG = os.environ.get("DJANGO_DEBUG", "0") == "1"
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "").split(",")

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": os.environ.get("DB_NAME", "shopdb"),
        "USER": os.environ.get("DB_USER", "root"),
        "PASSWORD": os.environ.get("DB_PASSWORD", ""),
        "HOST": os.environ.get("DB_HOST", "127.0.0.1"),
        "PORT": "3306",
        "OPTIONS": {"charset": "utf8mb4"},
    }
}

Use utf8mb4 so Hindi, Tamil and emoji all store correctly. Keep a .env file locally, add it to .gitignore, and load it with python-dotenv in manage.py.

One more decision to take on day one: if you might ever customise the user model, do it now with a custom user app. Changing it after the first migration is painful.

The commands you will use daily

Command What it does
runserver Development server with auto-reload (never in production)
makemigrations Turn model changes into migration files
migrate Apply migrations to the database
createsuperuser Make an admin login
shell A Python shell with Django loaded
check --deploy Audit production settings
test Run the test suite

Common mistakes

  • Forgetting to activate the virtual environment, then installing into the system Python.
  • Leaving SECRET_KEY and database passwords in settings.py and pushing to GitHub.
  • Omitting the app from INSTALLED_APPS and wondering why migrations are empty.
  • Running runserver in production.

Practice

Create a project called config with an app called billing, point it at a MySQL database through environment variables, and confirm python manage.py check passes with DJANGO_DEBUG=0 and a real ALLOWED_HOSTS value set.

B

Written by Bablu Kumar Jha

Founder, BeeProton AI · Mumbai, Maharashtra, India