RizTech Academy logo
RizTech Academy
Getting StartedLesson 2 of 430 min

Starting a project the right way

The first thing you do on a Django project shapes everything after it. Set it up carelessly and you fight your environment for weeks; set it up well and you barely think about it again. This lesson gets you from nothing to a running Django project — Nidaan, the clinic system we build across the course — the way a professional would, and explains why each step is what it is rather than having you copy commands blind.

Step 1: an isolated environment (never skip this)

Python projects must not share dependencies globally. Two projects will eventually need two different versions of the same package, and a global install makes that impossible — the classic "it works on my machine" mess. A virtual environment gives this project its own private set of packages:

mkdir nidaan && cd nidaan
python3 -m venv venv          # create an isolated environment in ./venv
source venv/bin/activate      # activate it (Windows: venv\Scripts\activate)

Once activated, your shell prompt shows (venv), and python and pip now refer to this project's isolated copies. Everything you install lands here, not system-wide. Deactivate with deactivate when you are done. Activate the venv every time you work on the project — forgetting is the single most common beginner confusion ("why can't it find Django?" — because you installed it in the venv but are not in it).

Step 2: install Django, and pin what you install

Inside the activated environment:

pip install "Django>=5.1,<5.2"

Two deliberate choices. We install a pinned range, not a bare pip install django, so the version is predictable — a project that silently upgrades its framework across a minor release is asking for surprise breakage. And immediately, we record what we installed:

pip freeze > requirements.txt

requirements.txt lists every package and its exact version, so anyone (including future you, or the deploy server) can recreate this environment with pip install -r requirements.txt. Commit requirements.txt; never commit the venv/ directory — the venv is machine-specific and large, the requirements file is the portable, reproducible record. This course uses Django 5.1.

Step 3: create the project — and the config convention

Now the command that scaffolds a Django project. Note the exact form, because the trailing dot matters:

django-admin startproject config .

This creates a Python package called config and a manage.py file in the current directory (the .). Why config and the dot? The naive django-admin startproject nidaan creates a nidaan/nidaan/ nested folder — a confusing double-nesting where the outer and inner folders share a name. Naming the settings package config and using . gives you a clean, flat layout where the repository is nidaan and the settings package is unambiguously config. It is a widely-used convention for exactly this reason. Your layout is now:

nidaan/
  manage.py            ← your command-line entry point for everything
  config/
    __init__.py
    settings.py        ← project configuration
    urls.py            ← the root URL map
    wsgi.py            ← entry point for traditional (sync) servers
    asgi.py            ← entry point for async servers
  venv/                ← (not committed)
  requirements.txt

manage.py is the tool you run for everything — starting the server, creating apps, running migrations, opening a shell. config/settings.py is where the project is configured. config/urls.py maps URLs to code. The two server files (wsgi.py, asgi.py) are entry points production servers use; you will not touch them until deployment.

Step 4: initialise the database and run the server

Django comes with built-in apps (auth, sessions, admin) that need database tables. Create them, then start the development server:

python manage.py migrate      # create the tables Django's built-in apps need
python manage.py runserver    # start the development server on http://127.0.0.1:8000/

migrate applies Django's initial migrations to a database — by default a db.sqlite3 file created right there, which is perfect for development (we move to PostgreSQL for production later). runserver starts a lightweight development server. Visit http://127.0.0.1:8000/ and you will see Django's rocket-ship welcome page — the confirmation that the install worked. That development server auto-reloads when you edit code, so you leave it running while you work.

The development server is for development only. It is single-threaded, unoptimised, and explicitly not built to face the public internet — the deployment module covers the real server. Seeing "runserver" in a production deploy is a red flag.

Step 5: the .gitignore, before your first commit

Initialise git and, crucially, ignore the things that must never be committed:

git init

Create a .gitignore with at least:

venv/
db.sqlite3
__pycache__/
*.pyc
.env

Why each: venv/ is machine-specific and huge; db.sqlite3 is local data, not code; __pycache__/ and *.pyc are compiled artefacts; and .env will later hold secrets (database passwords, the secret key) that must never reach a repository. Getting .gitignore right before the first commit saves you from the awkward job of scrubbing a committed secret from history later — a mistake that, for a real secret, means rotating it. Set it up now, once.

The setup checklist

Every new Django project, in order: make a folder → create and activate a venv → install a pinned Django and freeze requirements → startproject config . → migrate → runserver to confirm → git init with a correct .gitignore. Do these seven and you have a clean, reproducible, source-controlled starting point. Skip the venv or the .gitignore and you will pay for it — those two are where the pain lives.

Check your work

Why a virtual environment. It isolates this project's packages so versions do not collide with other projects or the system — and you must activate it every session.

Why pin Django and freeze requirements. A pinned range prevents surprise upgrades; requirements.txt records exact versions so the environment is reproducible. Commit it; never commit venv/.

Why startproject config .. The . scaffolds into the current directory and naming the package config avoids the confusing nidaan/nidaan/ double-nesting — a clean, conventional layout.

What manage.py is. The command-line entry point for everything — server, apps, migrations, shell.

What migrate and runserver do. migrate creates the tables Django's built-in apps need (default SQLite in development); runserver starts the auto-reloading development server — not for production.

What must be in .gitignore from the start. venv/, db.sqlite3, __pycache__/, *.pyc, .env — set before the first commit so a secret never reaches history.

Practice

  1. Create the nidaan project from scratch following all seven steps. Confirm the welcome page loads at http://127.0.0.1:8000/.
  2. Deactivate the venv and run python -c "import django"; read the ModuleNotFoundError. Reactivate and watch it succeed — proof of what the venv does.
  3. Open requirements.txt and read it. Delete the venv entirely, recreate it, and restore the environment with pip install -r requirements.txt — the reproducibility in action.
  4. Run django-admin startproject nidaan (no dot) in a throwaway folder and observe the double-nested layout, so you understand what the config . form avoids.
  5. Commit the project. Run git status and confirm venv/ and db.sqlite3 do not appear — proof the .gitignore works.
  6. Run python manage.py runserver 8001 and note you can choose the port; visit it.

Official documentation

Next: how a request flows through Django.

Stuck on this lesson?

Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.

About the internship