// django · overview

How Django works: the framework you already built

You've built nearly every piece of Django by hand across these guides — a WSGI callable, a route table, middleware, an ORM, templates — and watched the CSRF defense defeat a forged form. This overview assembles the map: the startproject skeleton file by file, the full life of a request through the framework, and a side-by-side of your ~150 lines against Django's modules. Two simulators run the pipeline and the correspondence.

mindmap — quick refresh Django — your hand-built stack, industrialized install & skeleton one venv, pip install django (6.1 ≈ 350k lines) startproject: settings, urls, wsgi/asgi, manage.py startapp: models, views, admin, migrations/ every generated file maps to a guide you did life of a request socket → gunicorn worker → wsgi.py callable 7 default middleware — the onion, written vertically urls.py scan → view(request, kwargs) ORM → SQL → template → HttpResponse → back out yours ↔ Django's App.__call__ ↔ get_wsgi_application() routes list ↔ urlpatterns view(environ, sid) ↔ view(request, sid) tiny filter() ↔ objects.filter() QuerySet Logging(GateKeeper(app)) ↔ MIDDLEWARE list the batteries you didn't build admin: free CRUD UI from model metadata auth: sessions + users + login_required migrations: schema generated from models defaults: CSRF token, SQL params, HTML escaping ON component map — go deeper each module owns one job from the request's journey wsgi/urls/middleware ↔ WSGI guide · models ↔ ORM guide templates ↔ SSR · forms/CSRF ↔ forms guide · auth ↔ auth guide admin & migrations: no guide yet — the new machinery path from here official tutorial parts ↔ these guides read error pages top-down — you know every layer

Prerequisites: this is the capstone — it assembles WSGI, the tiny ORM, HTML forms & CSRF, SSR, packaging, and OOP. Have at least WSGI and the ORM under your belt. Time: ~40 minutes reading, then the official tutorial.

Django is ~350,000 lines of Python, twenty years old (2005, named after guitarist Django Reinhardt), and runs Instagram. It is also — and this is the claim these guides have been quietly proving — a framework you have already built. A WSGI callable, a route table, a middleware onion, a self-describing ORM, template rendering: you wrote each one small — and the sixth piece, the CSRF token, you watched defeat a forged form in the forms guide. What Django adds is not new kinds of machinery; it's the same machinery industrialized, with twenty years of edge cases handled. So this guide is not a tutorial — the official one is excellent — it's the map that stops Django from ever feeling like magic.

Install and read the skeleton

Setup is the packaging workflow, verbatim (Windows: py -m venv .venv, then .venv\Scripts\activate):

python3 -m venv .venv && source .venv/bin/activate
pip install django                        # 6.1 at the time of writing
django-admin startproject foodsite
cd foodsite && python manage.py startapp orders

That generates a tree, and here's the point of this whole article — annotate it with where you've been:

foodsite/
├── manage.py                ← runs commands inside your venv'd project
├── foodsite/                ← the project: plumbing
│   ├── settings.py          ← config: MIDDLEWARE list, DATABASES, apps
│   ├── urls.py              ← the route table       → How WSGI works
│   ├── wsgi.py              ← the WSGI callable     → How WSGI works
│   └── asgi.py              ← its async sibling     → (same guide, last section)
└── orders/                  ← an app: your actual features
    ├── models.py            ← classes ↔ tables      → How ORMs work
    ├── views.py             ← request → response    → SSR labs, WSGI
    ├── admin.py             ← free CRUD UI          → (new! see below)
    ├── migrations/          ← schema history        → (new! see below)
    └── tests.py

Open wsgi.py and enjoy the punchline — after the comments it's two meaningful lines, ending in application = get_wsgi_application(). The entire framework is inside a callable with the exact signature you implemented from scratch. Gunicorn cannot tell your 40-line framework and Django apart, because there is nothing to tell apart.

The life of a request

Everything Django does happens inside one application(environ, start_response) call — so let's trace GET /students/42/ through the whole machine, station by station. You built every station; Django's contribution is the assembly. The seven middleware in a fresh settings.py are your onion written vertically — SecurityMiddleware, SessionMiddleware, CommonMiddleware, CsrfViewMiddleware, AuthenticationMiddleware, MessageMiddleware, XFrameOptionsMiddleware — request descending, response climbing, any layer able to short-circuit (that's CSRF rejection happening before your view ever runs):

Note what the trace makes obvious: a Django "view" is your WSGI view with better luggage — request is environ upgraded to an object (request.GET, request.POST pre-parsed, request.user attached by the auth middleware), and returning an HttpResponse replaces calling start_response by hand.

Yours ↔ Django's, line by line

The correspondence deserves to be exact, not hand-waved. Left column: code you have actually written in these guides. Right: the Django file where the same job lives:

Written out once, view-layer included:

# you wrote (tinyorm + framework.py):          # Django (models.py / views.py / urls.py):
class Student(Model):                          class Student(models.Model):
    name: str                                      name = models.CharField(max_length=100)
    course: str                                    course = models.CharField(max_length=100)

Student.filter(course="AI")                    Student.objects.filter(course="AI")

@app.route(r"/students/(?P<sid>\d+)/")        path("students/<int:sid>/", views.detail)

def detail(environ, sid):                      def detail(request, sid):
    return "200 OK", f"<h1>…{sid}</h1>"            s = Student.objects.get(pk=sid)
                                                   return render(request, "detail.html", {"s": s})

Differences worth respecting: Django's fields carry database detail (CharField(max_length=100)) because migrations generate real DDL from them; objects.filter() returns a lazy QuerySet (SQL runs on iteration, not on the call — the big upgrade over our eager tiny ORM); and render() is the SSR template merge with auto-escaping on by default.

The batteries you didn't build

Four additions have no counterpart in your hand-built stack — these are what you're actually adopting Django for:

  • The admin. Two lines in admin.py (admin.site.register(Student)) and Django serves a full create/read/update/delete UI for your models — generated from the same self-description your tiny ORM introspected. This is the killer feature that made Django famous in newsrooms.
  • Auth, complete. Everything authentication vs authorization described, built for real: sessions, users, groups, password hashing, @login_required. Our GateKeeper was just a path-prefix blocker — Django's auth middleware is the same short-circuit pattern grown into genuine session machinery.
  • Migrations. makemigrations diffs your models against schema history and writes the SQL for you — the CREATE TABLE you typed by hand in PostgreSQL 101, plus the ALTER TABLE for every schema change after it; migrate applies them in order, on any machine.
  • Secure defaults, stacked. Values through SQL placeholders (ORM guide), CSRF tokens checked by middleware (forms guide), template auto-escaping (SSR part 1's warning, made default), clickjacking and HTTPS headers. Django's philosophy: the safe path is the default path.

The component map: go deeper

Why does Django decompose into these particular modules? Because each one owns exactly one job from the request's journey — and every one of those jobs is something you've already done small. So use this table as a directory: whenever a component starts to feel like magic, the linked guide rebuilds it by hand.

Django componentThe job it ownsHow it works under the hood
wsgi.py / django.core.handlersspeak the server ↔ framework contractHow WSGI works
urls.py / django.urlsmatch the path, pick the viewHow WSGI works — routing; the patterns: How regular expressions work
settings.MIDDLEWAREwrap every request and responseHow WSGI works — the onion
django.http — HttpRequest, HttpResponsemodel the HTTP conversationHow HTTP works
views.pyturn a request into a responseSSR in pure Python, part 1 and part 2
models.py / django.db.models — the ORMtranslate objects ↔ rowsHow ORMs work
the database underneathstore and guard the dataPostgreSQL 101
django.templatemerge data into HTML, escaping by defaultSSR in pure Python, part 1 — the template merge
django.forms + CsrfViewMiddlewareread user input safelyHow HTML forms work
django.contrib.sessions + django.contrib.authwho are you, and what may you do?How auth works
manage.py runserver — the dev serverthe accept → parse → route → respond loopHow HTTP servers work
your venv + pip install djangoget the framework onto your machineHow Python packages work
django.contrib.staticfiles, gunicorn, the proxyserve it on the real internetHow deployment works — the one row that points ahead: on the roadmap it's your next guide, not one behind you
django.contrib.adminfree CRUD UI from model metadatano guide yet — it's generated from the ORM's self-description (How ORMs work)
django.db.migrationswrite schema history from your modelsno guide yet — the DDL it generates is PostgreSQL 101 by machine

Two rows say "no guide yet" on purpose: the admin and migrations are the genuinely new machinery you adopted Django for, and honest gaps beat pretend coverage. Everything else in the framework, you can now open from the inside.

Your path from here

Do the official Django tutorial next — it will feel like revision, and that's the intended effect. Part 1 (project setup) is the WSGI + packaging guides; part 2 (models, admin) is the ORM guide plus the free UI; part 3 (views, URLconfs) is the framework you wrote; part 4 (forms) is the forms guide with csrf_token finally explained by mechanism, not incantation. And when something breaks, read the error page top-down without fear: every frame in that traceback — middleware, URL resolver, view, ORM — is a layer you have built with your own hands.

Takeaways

  • Django is your stack, industrialized — WSGI callable, route table, middleware onion, self-describing ORM, template merge: nothing in the core is a new kind of thing.
  • The skeleton is a map, not a mystery — wsgi.py is your callable, urls.py your route list, models.py your tiny ORM, settings.MIDDLEWARE your onion written vertically.
  • A request crosses ~7 middleware, one URLconf, one view — and can be short-circuited early (CSRF, auth) exactly like your GateKeeper; responses climb back out through every layer.
  • request is environ with luggage — pre-parsed GET/POST, an attached user; HttpResponse replaces hand-rolled start_response.
  • Adopt Django for the batteries — admin, auth, migrations, lazy QuerySets, and safe-by-default settings are the 350k lines you shouldn't rewrite.
  • Debug fearlessly — every layer in a Django traceback is one you've built small; read top-down and name the station.

References

  • Django Software Foundation. (n.d.). Django at a glance (Django documentation). Retrieved August 17, 2026, from https://docs.djangoproject.com/en/stable/intro/overview/
  • Django Software Foundation. (n.d.). Design philosophies (Django documentation). Retrieved August 17, 2026, from https://docs.djangoproject.com/en/stable/misc/design-philosophies/
  • Django Software Foundation. (n.d.). FAQ: General (Django documentation). Retrieved August 17, 2026, from https://docs.djangoproject.com/en/stable/faq/general/
  • Django Software Foundation. (n.d.). Writing your first Django app, part 1 (Django documentation). Retrieved August 17, 2026, from https://docs.djangoproject.com/en/stable/intro/tutorial01/
  • Holovaty, A., & Kaplan-Moss, J. (2009). The definitive guide to Django: Web development done right (2nd ed.). Apress.