本文目录导读:
我们用 一个最简单的博客文章列表页面 来实战解释 Django 的 MTV 架构。
在这个案例里,用户访问 http://127.0.0.1:8000/articles/,就会看到所有已发布的文章标题和摘要。
第一步:先搞清 MTV 三个角色
| 角色 | 全称 | 类比(餐厅例子) | 实际代码里是什么 |
|---|---|---|---|
| M | Model(模型) | 厨房的食材仓库和菜谱 | 定义数据库里的数据结构(如:文章表) |
| T | Template(模板) | 餐厅摆盘的盘子、菜单样式 | 纯 HTML + 占位符,决定用户看到的样子 |
| V | View(视图) | 厨师 + 服务员 | 从数据库拿数据,填进模板,返回给用户 |
注意:MVC 里的 Controller(控制器)在 Django 里通常由 URLconf(路由) 和 View 里的业务逻辑 共同承担,但 Django 强调 MTV,重点是把数据处理(View)和界面表现(Template)彻底分离。
第二步:实战案例——博客文章列表
第 1 层:Model(模型)—— 定义“文章是什么”
在 models.py 里:
from django.db import models
class Article(models.Model):= models.CharField(max_length=200) # 文章标题
content = models.TextField() # 正文
pub_date = models.DateTimeField() # 发布日期
is_published = models.BooleanField(default=True)
def __str__(self):
return self.title
这层做了什么?
告诉 Django:“我要在数据库里建一张 Article 表,字段有标题、内容、日期等。” 数据库会自动生成。
第 2 层:View(视图)—— 核心业务逻辑
在 views.py 里:
from django.shortcuts import render
from .models import Article
def article_list(request):
# 1. 从数据库拿数据(M)
articles = Article.objects.filter(is_published=True).order_by('-pub_date')
# 2. 把数据填进模板并返回(V + T 联动)
return render(request, 'blog/article_list.html', {'articles': articles})
这层做了什么?
- 扮演“厨师”:查询数据库,只拿已发布的文章,按日期倒序排列。
- 扮演“服务员”:把处理好的数据(
articles)放进上下文({'articles': articles}),传给模板。
第 3 层:Template(模板)—— 呈现给用户
在 templates/blog/article_list.html 里:
<!DOCTYPE html>
<html>
<head><title>博客列表</title></head>
<body>
<h1>最新文章</h1>
<ul>
{% for article in articles %}
<li>
<h2>{{ article.title }}</h2>
<p>{{ article.content|truncatewords:30 }}</p>
<small>发布于:{{ article.pub_date|date:"Y-m-d" }}</small>
</li>
{% endfor %}
</ul>
</body>
</html>
这层做了什么?
- 纯 HTML 结构,但用 和 做占位符。
- 循环显示每篇文章的标题、截断后的摘要、格式化后的日期。
- 完全不关心数据是从哪个数据库表来的,也不关心逻辑。
第 4 层:URL 路由(穿针引线)
在 urls.py 里:
from django.urls import path
from . import views
urlpatterns = [
path('articles/', views.article_list, name='article-list'),
]
这一步不是 MTV 核心组件,但它是“入口”:告诉 Django,当用户访问 /articles/ 时,去执行 views.article_list 函数。
第三步:完整流程(用户敲 URL 后一秒内发生的事)
- 用户输入
http://.../articles/ - Django URLconf 匹配到
views.article_list - View 执行:
- 调用
Article.objects.filter(...)—— 这直接操作了 Model(查询数据库) - 拿到一个 Python 对象列表(QuerySet)
- 调用
- View 调用
render(),把数据传入 Template - Template 渲染:把
{{ article.title }}替换成实际标题,生成纯 HTML - View 返回
HttpResponse(内含最终 HTML)给浏览器 - 用户看到漂亮的文章列表页面
为什么 MTV 比“一个人全干”好?
- Model 和 View 分离:换数据库(比如从 SQLite 换到 PostgreSQL)只需改模型配置,视图代码不变。
- View 和 Template 分离:设计师可以改 HTML 模板,完全不碰 Python 逻辑,程序员可以加业务逻辑,不碰 HTML。
- 可测试性:可以单独测试模型(数据是否正确)、视图(响应是否 200)、模板(变量是否存在)。
M(Model) 告诉 Django 数据长什么样;V(View) 告诉 Django 怎么处理数据(查询、过滤、排序);T(Template) 告诉 Django 数据最终穿什么“衣服”展示给用户,三者各司其职,通过 URL 路由串联起来。