Django already encodes the patterns (MTV, and what that means)
Before this module discusses design patterns in Django, it has to start with an unusual truth: Django already is a set of patterns. Where a bare language like Java hands you a blank canvas and a catalogue of patterns to impose structure, Django hands you the structure already built in. Understanding that changes how you should think about patterns here — many of the classic "Gang of Four" patterns are already provided by the framework, and reaching for them by hand is usually reinventing something Django gives you. This lesson sets that frame for the whole module.
A framework is opinionated architecture
The difference between a library and a framework is who is in charge. You call a library; a framework calls you. Django decides the overall shape of your application — how a request flows, where data lives, how it is presented — and you fill in the specifics. That imposed shape is itself an architectural pattern, chosen and enforced for you. When people ask "what design patterns should I use in Django?", the first answer is: the ones the framework already made you use. Fighting or duplicating them is the most common architecture mistake beginners make here.
MTV: the pattern you are already following
Django's core architecture is MTV — Model, Template, View — its take on the classic Model-View-Controller (MVC) separation:
- Model — your data and the behaviour of that data (the ORM, your models). The "what".
- Template — presentation, the HTML. The "how it looks".
- View — the logic that connects a request to a model and a template. The "what happens".
This is the separation of concerns pattern, built in. You did not choose to separate data from presentation from request-handling — Django made you, by giving you three separate places for them. Every time you put a query on a model, formatting in a template, and plumbing in a view, you are applying an architectural pattern without naming it. The best-practices module's "logic in the right layer" is exactly this pattern, enforced.
The Gang of Four patterns Django already gives you
Many of the famous object-oriented design patterns exist in Django — you just do not implement them, because the framework does. A few concrete ones:
- Active Record — a model object that both holds data and knows how to save/load itself
(
patient.save()). Django's ORM is the Active Record pattern; you never build a separate data-access object. - Template Method — the class-based generic views (
ListView,CreateView) define a skeleton and let you override hook methods (get_queryset,get_context_data). That is the Template Method pattern, and DRF's generic views too. - Decorator —
@login_required,@permission_required,@cache_pagewrap a view with added behaviour. Python decorators applied to views are literally the Decorator pattern. - Observer — Django's signals (
post_saveand friends) let objects react to events without the sender knowing the receivers. That is the Observer pattern (and the signals lesson argues about when not to use it). - Singleton — the settings object, the app registry: single shared instances Django manages for you.
The lesson from the list: you are already using design patterns constantly — through the framework. Implementing your own Active Record layer, your own observer system, or your own template-method view base would be duplicating what Django provides, adding code and confusion for no benefit.
So what patterns are left to choose?
If Django provides so many patterns, what is this module for? The genuinely useful, chosen patterns in a Django project are a small set — the ones that address problems the framework does not solve for you, which arise as an application grows:
- Where multi-model business logic lives — the fat-model-versus-service-layer question (next lesson), which Django deliberately leaves to you.
- Encapsulating query logic — custom managers as a lightweight repository pattern (the managers lesson), building on what you already learnt.
- Reacting to events well — signals, and the strong case for often not using them.
- Structuring the project as it grows beyond a handful of apps.
These are the decisions Django leaves open, and they are where thoughtful pattern choices actually help. The rest of this module is those — a short list, because most structure is already given.
The warning this module is built on: do not import the Java catalogue
The most important point, and the one the skill this course is written to insists on: do not transliterate patterns from Java (or a patterns textbook) into Django. A great deal of "enterprise" pattern machinery — abstract factories, elaborate builder hierarchies, dependency-injection containers, repository classes wrapping the ORM — exists to work around limitations Python and Django do not have. Python has first-class functions (so many "patterns" are just a function), the ORM is already an Active Record with a query API (so a repository wrapping it is often pure overhead), and Django's structure already separates concerns. Importing the full catalogue produces code that is more complex and less idiomatic than plain Django. The honest guidance for the whole module: most "pattern" code in the wild is a pattern applied where it was not needed — reach for a pattern only when a real, felt problem in this project calls for it, and prefer the simple, Pythonic, Django-idiomatic solution first.
Check your work
Framework versus library. You call a library; a framework calls you — Django imposes the application's shape, which is itself an architectural pattern you follow by default.
MTV. Model (data + behaviour), Template (presentation), View (request logic) — Django's built-in separation-of-concerns pattern; "logic in the right layer" is this pattern enforced.
Patterns Django already gives you. Active Record (the ORM), Template Method (generic views), Decorator (view decorators), Observer (signals), Singleton (settings) — you use them through the framework, not by hand.
What is left to choose. A small set: where multi-model logic lives, encapsulating queries (managers), using signals well, and structuring a growing project — the problems Django leaves open.
The warning. Do not transliterate the Java pattern catalogue — Python's functions, the ORM, and Django's structure already solve what many patterns work around; most wild "pattern" code is unneeded. Prefer the simple, idiomatic solution.
Practice
- For each of MTV's three parts, name a file in Nidaan where that concern lives, and confirm the separation is real.
- Identify the design pattern behind
patient.save(),@login_required, aListView, and apost_savesignal — matching each to a Gang of Four pattern. - Reason about why implementing your own data-access layer over the ORM duplicates Active Record for no gain.
- Find an "enterprise" pattern (abstract factory, repository class, DI container) and argue what Python/ Django feature makes it usually unnecessary here.
- List the handful of patterns actually worth choosing in a Django project, and the problem each solves.
- Take a piece of code you were tempted to "pattern up" and write the plain, idiomatic Django version; compare.
Official documentation
- Django — FAQ: Is Django MVC? — Django's own take on MTV versus MVC.
- Django — Design philosophies — The opinions the framework encodes.
- Refactoring Guru — Design Patterns — The classic catalogue, to recognise what Django already provides.
Next: the service-layer debate — fat models versus services.
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