Definition
Putting a website online is almost never about writing the feature you actually care about. Before it come a database to open, URLs to map onto code, passwords to store without putting them at risk. That work is the same everywhere, and it still eats up the first weeks of every project.
Django answers that annoyance. This web framework written in Python, shipped as a package, hands you the plumbing already written and already wired: URL routing, database access, templates, forms, user accounts, administration. What is left to write is the business logic, the one part nobody can write in your place.
The promise shows better on an example. The file below does nothing but describe what an article is: three pieces of information and their type.
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
published_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.titleFrom that description alone, Django works out a database table, an input form and an admin screen where a non technical person publishes without seeing a line of code. The __str__ method, a Python magic method, picks the text shown wherever the article appears. The whole thing installs with pip, inside a virtual environment dedicated to the project.
What it saves you from writing
What Django supplies stays abstract until you have tried to write it yourself: reading an HTTP request, mapping a URL to a function, opening a database connection, building SQL without getting injected, hashing passwords.
Several of those parts are security topics, and that changes the nature of the problem. A layout mistake is fixed within the day; a mistake in how passwords are stored is not visible at all, until the day the database leaks. Django settles them for you, with defaults that hold up.
The comfort has a price: you inherit a project layout and conventions to learn before being productive. The first week runs slower than with a minimal tool, and the ratio flips when user accounts show up: sign up, login and access rights are already there, when they would have cost days.
Against Flask and FastAPI
The question is not which one has the most features, it is how many decisions each of them leaves to you. Read the table in that direction: on the left what is settled, on the right what you will have to wire yourself.
| On this point | Django | Flask | FastAPI |
|---|---|---|---|
| Database | ORM included | Your choice | Your choice |
| Administration | Generated | To be written | To be written |
| Accounts and login | Included | Extension | To be written |
| Natural ground | Site with pages and data | Small custom service | Typed API |
Django brings nothing to a script, a bot or a three route API: it would mean carrying a whole structure for a single file. As soon as a project has users who log in, content edited by a team and a relational database, redoing all of that by hand amounts instead to rewriting Django, less safely.
That leaves the pure, strongly typed API: FastAPI backed by Pydantic is more direct there, type hint annotations being enough to validate incoming data.
The ORM, its real centre of gravity
Without a framework, a website ends up with scraps of SQL scattered across strings, connected to nothing else in the code. Django's ORM removes that problem by treating every table as an ordinary Python object.
The mechanism reuses what you already know: every table is described by a class that gains its powers by inheritance from models.Model, and every column by an attribute. Queries are then written in Python, and the SQL is produced and escaped for you.
recent = Article.objects.filter(published_at__year=2026).order_by("-published_at")[:5]That line reads without knowing any SQL: keep the articles published in 2026, sort them by date, take only the first five.
Then comes the question everyone asks: what happens to the database the day the class changes? Two commands work out the difference and apply it without losing the rows already stored.
python manage.py makemigrations
python manage.py migrateEach change leaves a file versioned along with the code, which a colleague replays in one command. That model plus migration pair is what explains why so many teams stay on Django once a project has shipped.
The two first project mistakes
The first one is not a syntax mistake, it is a structural one. Django separates the project, which holds the configuration, from the applications, which each hold one area. Many beginners pile everything into a single application: it holds for six months, then nothing can be isolated or tested on its own any more. One application per area from day one is enough to avoid it.
The second one is invisible while writing and shows up under load, and it has a name: the N+1 query.
Displaying a hundred articles with the author of each one fires a hundred and one queries: the ORM fetches the relation at the moment the template reads it, long after the initial query. The page feels instant locally, on ten articles, and collapses in production. The fix takes one call, select_related or prefetch_related, placed on the original query.
Frequently asked questions
Do you need to know Python before learning Django?
Yes, and not just the syntax. The framework rests on classes, on splitting code into modules and on the decorator, used here to reserve a page for logged in members. Its error messages also assume you can read a call stack: otherwise you will look inside Django for a mistake that came from your own code.
Is Django suitable for an API with no HTML pages?
Yes, with Django REST Framework, an extension that turns models into json responses and covers pagination, permissions and validation. The calculation depends on the starting point: on an existing Django codebase it avoids redeclaring models already written, while for a standalone API started from scratch, FastAPI asks for less ceremony.
Does Django handle asynchronous code?
Partly. Views accept async and await since version 3.1, and the ORM exposes asynchronous calls, but a large share of the ecosystem stays synchronous. On a classic website the gain is nil: asynchronous code pays off on connections held open, a chat or a live feed, not on pages that answer in a few milliseconds.