MTV Pattern

Difficulty: Beginner

Django follows the MTV (Model-Template-View) architectural pattern, which is Django's variation of the more widely known MVC (Model-View-Controller) pattern. Understanding MTV is essential because it defines how you structure your code and how data flows through a Django application.

The Model layer handles data and business logic. Models are Python classes that define the structure of your database tables. Each model class maps to a database table, and each attribute maps to a column. Django's ORM translates Python operations into SQL queries, so you rarely need to write raw SQL. Models also contain methods for data manipulation and validation. The Model is equivalent to MVC's Model - it is the single, definitive source of information about your data.

The Template layer handles presentation. Templates are HTML files with special syntax (Django Template Language) that allow you to insert dynamic data. Templates contain variables ({{ variable }}), tags ({% tag %}), and filters ({{ variable|filter }}). They define how data should be displayed to the user. In MVC terms, the Template corresponds to the View - it is responsible for the visual representation.

The View layer handles the business logic and acts as the bridge between Models and Templates. Views receive HTTP requests, interact with the Model to fetch or manipulate data, and return HTTP responses (usually by rendering a Template with context data). In MVC terms, Django's View corresponds to the Controller - it coordinates what happens in response to user requests.

This naming difference between MVC and MTV often causes confusion in interviews. In MVC, the View is the visual layer and the Controller handles logic. In Django's MTV, the Template is the visual layer and the View handles logic. The mapping is: MVC Model = MTV Model, MVC View = MTV Template, MVC Controller = MTV View. The underlying concepts are identical; only the naming differs.

The request-response cycle in Django works as follows: (1) A user's browser sends an HTTP request to a URL. (2) Django's URL dispatcher matches the URL to a view function or class. (3) The view executes business logic, often querying the database through models. (4) The view passes data (context) to a template. (5) The template renders HTML with the dynamic data. (6) Django returns the rendered HTML as an HTTP response to the browser.

Django adds an important component not explicitly in the MTV acronym: the URL dispatcher (URLconf). The URLconf maps URL patterns to views and acts as a routing table. Without it, Django would not know which view to call for a given URL. The URL dispatcher is defined in urls.py files and uses the path() and re_path() functions to define patterns.

The MTV pattern promotes separation of concerns. Database logic stays in models, presentation stays in templates, and request handling stays in views. This separation makes the codebase easier to maintain, test, and extend. You can change the visual design (templates) without touching the business logic (views), or refactor the database schema (models) without changing the presentation layer.

Code examples

Complete MTV Flow Example

# 1. MODEL (models.py)
from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    published = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

# 2. VIEW (views.py)
from django.shortcuts import render
from .models import Article

def article_list(request):
    articles = Article.objects.all().order_by('-published')
    return render(request, 'blog/article_list.html', {
        'articles': articles,
    })

# 3. TEMPLATE (templates/blog/article_list.html)
# {% for article in articles %}
#   <h2>{{ article.title }}</h2>
#   <p>{{ article.content|truncatewords:50 }}</p>
#   <small>{{ article.published|date:"M d, Y" }}</small>
# {% endfor %}

# 4. URL (urls.py)
from django.urls import path
from . import views

urlpatterns = [
    path('articles/', views.article_list, name='article-list'),
]

This shows a complete MTV cycle: The Model defines the Article data structure, the View queries articles and passes them as context, the Template renders the articles as HTML, and the URL pattern maps /articles/ to the view.

MVC vs MTV Mapping

# MVC Pattern (Rails, Spring, Laravel)
# Model      -> Data & business logic
# View       -> HTML/UI presentation
# Controller -> Request handling & coordination

# Django MTV Pattern
# Model    -> Data & business logic        (same as MVC Model)
# Template -> HTML/UI presentation         (same as MVC View)
# View     -> Request handling & coordination (same as MVC Controller)

# The concepts are identical, only the names differ:
# MVC Controller == Django View
# MVC View       == Django Template

The key difference is naming. Django's View handles logic (like MVC's Controller), and Django's Template handles presentation (like MVC's View). This is a common interview question.

Request-Response Cycle

# The Django Request-Response Cycle:
#
# Browser sends GET /articles/
#       |
#       v
# URL Dispatcher (urls.py)
#   -> matches 'articles/' to views.article_list
#       |
#       v
# View (views.py)
#   -> article_list(request) is called
#   -> queries Article.objects.all() [Model layer]
#   -> passes articles to template [Template layer]
#       |
#       v
# Template (article_list.html)
#   -> renders HTML with article data
#       |
#       v
# HttpResponse sent back to browser
#   -> browser renders the HTML page

Every Django request follows this cycle. The URL dispatcher routes the request to the correct view, the view uses models to get data and templates to render HTML, and the response is sent back to the client.

The URL Dispatcher

# project/urls.py (root URL configuration)
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls')),
    path('shop/', include('shop.urls')),
]

# blog/urls.py (app-level URL configuration)
from django.urls import path
from . import views

app_name = 'blog'
urlpatterns = [
    path('', views.post_list, name='post-list'),
    path('<int:pk>/', views.post_detail, name='post-detail'),
    path('create/', views.post_create, name='post-create'),
]

Django uses a two-level URL configuration. The root urls.py includes app-level URL files using include(). Each app defines its own URL patterns. The app_name enables URL namespacing to avoid name collisions.

Key points

Concepts covered

MTV, Model, Template, View, MVC, Request-Response Cycle