Django入门:理清MVT与请求生命周期,从零搭建留言板
2026/8/31 1:54:58 网站建设 项目流程

很多新手学 Django,最容易遇到的情况是:教程翻了一堆,视频看了不少,python manage.py runserver跑起来了,甚至还跟着做了一个投票系统,但合上教程,让自己从零开始写一个新的 Web 项目,还是不知道该先建哪个文件,更搞不清 MTV、ORM、URL 路由这些概念是怎么串起来的。

这是学习 Django 最典型的瓶颈,不是语法不会,而是没有抓住主线

Django 是一个“约定大于配置”的全栈框架,它把 Web 开发中大部分重复工作都封装好了。但正因为封装层级多,概念名词多,新手很容易被各种细节带偏,最后陷入“学了一堆配置项,却写不出一个页面”的困境。

这篇文章不打算罗列 Django 的所以功能,而是帮你梳理一条从“浏览器输入网址”到“浏览器显示页面”的完整主线。只要能沿着这条主线把请求生命周期跑通,Django 的学习难题就解决了大半。读完这篇文章,你会理解 Django 的核心工作流程,并能独立写一个具备数据库读写和页面渲染的小项目。

1. 为什么 Django 容易让新手“学了就忘”

先说一个判断:Django 学习的核心不是记住 API,而是理解请求的流转方向。

如果你打开 Django 的官方文档,会发现它内容非常多:模型字段、查询表达式、表单系统、认证系统、Admin 后台、中间件、信号、缓存、测试……光是模型字段就有几十种,新手如果按照目录逐章阅读,读到最后基本已经忘了第一张写了什么。

这不是你学习能力的问题,而是官方文档的目录结构本身是“参考手册”式的,不是“学习路径”式的。参考手册适合有经验的开发者在遇到特定问题时查阅,但不适合新手建立整体认知。

Django 真正的上手路径应该是:

浏览器请求 -> URL 路由 -> 视图函数 -> 模型/数据库 -> 模板渲染 -> 返回响应

这条链路里的每一环,单独拿出来都不算难懂。难的是新手在没跑通完整链路之前,就先扎进某一个环节去深挖。比如一上来就研究 ORM 怎么写复杂查询,或者花大量时间研究 Admin 后台怎么定制,结果连一个最简单的“写死在代码里的页面”都还没跑通。

因此这篇文章会用一条完整的最小业务串起 Django 的核心概念。先建立整体骨架,再逐步往里填充器官,这种方式比逐章读文档高效得多。

2. 先建立 Django 的核心概念:MVT 不是一个摆设

Django 的架构模式叫 MVT,也就是 Model、View、Template。很多新手第一次看到这三个词,会和传统 MVC(Model-View-Controller)混淆,特别是“View”的含义在两个架构里完全不同。

在传统 MVC 中,View 用来展示数据,Controller 负责接收请求和处理业务逻辑。而在 Django 的 MVT 中:

  • Model 负责和数据库打交道,定义数据结构。
  • View 负责接收 HTTP 请求,执行业务逻辑,并准备要返回的数据,它实际上承担了 Controller 的工作。
  • Template 负责 HTML 渲染,也就是把 View 传来的数据填进页面模板。

用一个通俗类比:Django 的 View 相当于餐厅里的服务员,负责接单(接收请求)、告诉后厨要做什么(调用 Model 查数据)、再把做好的菜端给客人(用 Template 渲染后返回响应)。Model 是后厨和食材仓库,Template 是摆盘和菜品外观。

新手最容易犯的错误,是把 Django 的 View 理解成“页面展示”。如果你看到代码里有一个def index(request)就觉得它是页面,那后面看官方文档时会在 Class-Based Views(类视图)这儿彻底迷失。正确的心智模型是:View 是处理请求的函数或类,它返回什么,浏览器就收到什么

理解了这一点,再看 Django 的项目结构会清晰很多。一个标准的 Django 项目通常包含:

mysite/ ├── manage.py └── mysite/ ├── __init__.py ├── settings.py ├── urls.py ├── asgi.py └── wsgi.py

其中settings.py是全局配置,urls.py是 URL 路由入口。而每个业务功能会被拆成一个独立的 app,比如用户模块、文章模块、订单模块。App 是 Django 里的模块化单元,一个项目可以有多个 app,每个 app 有自己独立的models.pyviews.pyurls.py

3. Django 的版本选择和快速上手步骤

Django 目前的主流使用版本是 4.x/5.x 及后续稳定版,具体版本以你开始学习时的官方稳定版为准。本文的重点是通用开发思路,版本差异不构成主要障碍,因为核心概念在 Django 2.x 之后基本保持稳定。

学习 Django 之前,建议先保证 Python 环境是 3.8 或更高版本,Python 3.8 以下版本会逐步失去 Django 官方支持。在开始安装 Django 之前,强烈建议先创建一个独立的虚拟环境,这是 Python 项目开发的基本素养,能避免不同项目之间依赖污染。

创建虚拟环境并安装 Django 的命令如下:

# 创建虚拟环境 python3 -m venv myenv # 激活虚拟环境 # Linux / macOS source myenv/bin/activate # Windows myenv\Scripts\activate # 安装 Django pip install django # 验证安装 python -c "import django; print(django.get_version())"

以上操作完成后,你就可以在当前环境的任意目录下创建一个新的 Django 项目:

django-admin startproject mysite cd mysite python manage.py runserver

如果一切正常,浏览器访问http://127.0.0.1:8000/会看到 Django 的默认欢迎页。很多新手到这里就以为“我已经掌握了 Django”,然后开始照着文档抄代码,越抄越乱。

实际上这一步只代表你的环境没问题,你还没有创建任何业务代码。Django 的学习主线,要从一个 app 的创建开始往前走。

4. 从零创建一个完整的最小 Django 应用

为了不陷入抽象概念,我们用一个实际场景贯穿整篇文章:做一个最简单的“留言板”。

这个留言板功能非常简单:用户访问首页,能看到历史留言列表;在页面底部有一个表单,填写昵称和留言内容后提交,刷新页面能看到新增的留言。

功能虽小,但它覆盖了 Django 的核心链路:URL 路由、视图函数、模型定义、数据库迁移、模板渲染、表单提交、数据写入、数据读取。把这套流程跑通,你就能理解 Django 的主体架构了。

4.1 创建一个 app

在项目根目录下执行:

python manage.py startapp message

执行完成后,项目里会出现一个message目录,里面包含models.pyviews.pyadmin.pymigrations/等文件。在 Django 中,一个 app 就是一个可复用的业务模块,你可以把它理解成一个“功能包”。这里不深入讨论 app 和项目的区别,只需要知道:项目是网站的配置容器,app 是具体的业务代码。

创建完 app 之后,要在mysite/settings.pyINSTALLED_APPS列表里注册它:

# mysite/settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'message', # 注册我们创建的 app ]

如果不注册,Django 后续执行数据库迁移时不会识别这个 app 里的模型。

4.2 定义数据模型

message/models.py中写入留言的数据结构:

# message/models.py from django.db import models class Message(models.Model): nickname = models.CharField(max_length=50, verbose_name='昵称') content = models.TextField(verbose_name='留言内容') created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') class Meta: verbose_name = '留言' verbose_name_plural = verbose_name ordering = ['-created_at'] def __str__(self): return f'{self.nickname}: {self.content[:20]}'

这里解释三个关键点:

  • CharField是短文本字段,必须指定max_lengthTextField是长文本字段;DateTimeField是时间字段,auto_now_add=True表示创建记录时自动填充当前时间。
  • Meta类里的ordering = ['-created_at']让查询结果默认按创建时间倒序,这样最新留言排在前面。
  • __str__方法决定了这条记录在 Admin 后台和在调试时的展示形式。

4.3 生成并执行数据库迁移

模型定义之后,需要把它“翻译”成数据库表。这一步在 Django 里叫迁移(migration)。

python manage.py makemigrations python manage.py migrate

makemigrations会根据模型变化生成迁移文件,migrate会把迁移文件真正应用到数据库。如果这两个命令没有报错,说明模型定义没有问题。你可以用sqlmigrate查看 Django 生成的 SQL 语句:

python manage.py sqlmigrate message 0001

这一步能帮你理解 ORM 的底层原理:Django 的模型最终会被翻译成 SQL 的CREATE TABLE语句。新手可以把这个命令当作学习 SQL 的辅助工具,但不建议在生产环境频繁使用。

4.4 编写视图函数

现在写第一个视图函数。我们的视图需要做两件事:读取数据库里的留言列表、把列表交给模板展示。同时还要处理表单提交,但因为表单提交涉及 POST 请求,我们可以先不处理,只展示数据。

# message/views.py from django.shortcuts import render from .models import Message def index(request): message_list = Message.objects.all() context = { 'message_list': message_list, } return render(request, 'message/index.html', context)

这段代码虽然短,但包含了三个核心动作:

  • 查询数据:Message.objects.all()通过 ORM 从数据库中查询所有留言记录。查询结果是 QuerySet,可以像列表一样遍历。
  • 准备数据字典:context是模板渲染时需要的数据集合,模板里用变量名message_list就能拿到这个数据。
  • 返回响应:render函数把模板文件和数据字典组合起来,生成最终的 HTML 字符串,并通过 HTTP 响应返回给浏览器。

4.5 配置 URL 路由

有了视图,还需要告诉 Django:当用户访问哪个网址时,由哪个视图来处理。在message目录下新建一个urls.py文件:

# message/urls.py from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), ]

然后再在项目的总路由文件mysite/urls.py中把 app 的路由包含进来:

# mysite/urls.py from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include('message.urls')), ]

这里用includemessage应用的路由挂载到项目根路径下。以后每次新增一个功能模块,只需要在 app 内部维护自己的urls.py,项目的总路由保持整洁。

4.6 创建模板文件

Django 默认会到每个 app 下面的templates目录里找模板文件。创建message/templates/message/index.html

<!-- message/templates/message/index.html --> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>留言板</title> </head> <body> <h1>留言板</h1> <ul> {% for message in message_list %} <li>{{ message.nickname }} 说:{{ message.content }}</li> {% empty %} <li>还没有留言,快来抢沙发!</li> {% endfor %} </ul> </body> </html>

注意模板语法里的两个关键点:{% for %}是 Django 模板标签,用于循环;{{ message.nickname }}是模板变量,用于输出数据。{% empty %}表示在没有数据时渲染的提示内容。

现在再次运行python manage.py runserver,访问http://127.0.0.1:8000/,就能看到留言板页面了。虽然此时数据库里还没有数据,页面会显示“还没有留言”。

到这里为止,你已经完成了 Django 核心链路的一半:URL -> View -> QuerySet -> Template -> Response。这也是入门 Django 需要记住的第一条主线。

5. 让页面真正“活”起来:处理表单提交

目前页面只能读数据,还不能写数据。要让用户能提交留言,需要加上表单处理逻辑。这是 Django 开发中“数据回写”的关键环节,也是新手最容易出错的地方。

5.1 在模板中加入表单

修改index.html,在页面底部添加一个表单:

<!-- message/templates/message/index.html --> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>留言板</title> </head> <body> <h1>留言板</h1> <ul> {% for message in message_list %} <li>{{ message.nickname }} 说:{{ message.content }}</li> {% empty %} <li>还没有留言,快来抢沙发!</li> {% endfor %} </ul> <hr> <h2>发表留言</h2> <form method="post" action="{% url 'index' %}"> {% csrf_token %} <p> <label>昵称:</label> <input type="text" name="nickname" required> </p> <p> <label>内容:</label> <textarea name="content" required></textarea> </p> <button type="submit">提交</button> </form> </body> </html>

这里的核心是{% csrf_token %}。Django 默认开启了 CSRF(跨站请求伪造)防护机制,所有使用 POST 方式提交的模板表单都必须包含这个 token,否则请求会被 Django 直接拒绝,返回 403 错误。这是新手最容易踩的坑。

5.2 在视图中处理 POST 请求

修改message/views.py,让视图既能处理 GET 请求展示页面,又能处理 POST 请求保存数据:

# message/views.py from django.shortcuts import render, redirect from django.views.decorators.http import require_http_methods from .models import Message @require_http_methods(['GET', 'POST']) def index(request): if request.method == 'POST': nickname = request.POST.get('nickname', '').strip() content = request.POST.get('content', '').strip() if nickname and content: Message.objects.create(nickname=nickname, content=content) return redirect('index') # 如果字段为空,也可以回到页面并给出错误提示 # 这里为保持示例简洁,直接返回重定向 message_list = Message.objects.all() context = { 'message_list': message_list, } return render(request, 'message/index.html', context)

这段代码有两个值得注意的地方:

  • request.method判断是 GET 还是 POST 请求。
  • 数据校验应该放在服务端,绝不能只依赖前端的required属性。示例中用strip()去掉首尾空格,并通过if nickname and content做非空判断。
  • Message.objects.create(...)是 ORM 的快捷写入方式,它等价于先实例化对象再调用save()
  • 写入成功之后使用redirect('index')做重定向,避免用户刷新页面时重复提交。这符合“Post/Redirect/Get”模式,是 Web 开发的基本工程规范。

现在再次运行项目,在表单里输入昵称和内容并提交,页面会出现新留言。整个“写入-读取-展示”的闭环已经打通。

6. 使用 Django Admin 后台:零成本的管理工具

Django 自带一个功能强大的 Admin 后台,这一点是很多初学者没有重视的。不需要写一行前端代码,就能获得一个用来管理数据的后台界面。

要让 Admin 后台能管理Message模型,需要在message/admin.py里注册:

# message/admin.py from django.contrib import admin from .models import Message @admin.register(Message) class MessageAdmin(admin.ModelAdmin): list_display = ('nickname', 'content', 'created_at') search_fields = ('nickname', 'content')

注册后,还需要创建一个可以登录后台的管理员账号:

python manage.py createsuperuser

按提示输入用户名、邮箱(可留空)和密码。然后重新运行runserver,访问http://127.0.0.1:8000/admin/,用刚才创建的账号登录,就能看到一个自己的管理后台。

list_display定义列表页展示的字段,search_fields定义搜索框可以搜索的字段。对于真实项目,Django Admin 可以作为运营人员的后台入口,也可以作为开发阶段的调试工具,性价比极高。

这里要提醒一点:Django Admin 不是万能的,它的角色是“管理后台”,不适合直接暴露给外部普通用户使用。如果需要面向用户的注册、登录、个人中心等功能,应该自己用 Django 的认证模块和表单系统来开发。

7. 运行结果验证与常见问题排查

7.1 如何判断项目是否正常

运行python manage.py runserver后,如果页面能正常打开,并且你能完成以下操作,说明核心链路已经跑通:

  • 访问http://127.0.0.1:8000/能看到留言板页面。
  • 通过表单提交一条留言,页面刷新后能看到新留言。
  • 访问http://127.0.0.1:8000/admin/能登录后台,并在后台看到和管理留言数据。

如果页面报错,不要慌张。Django 的调试模式下会在页面上显示完整的错误信息和堆栈跟踪,这是学习阶段最好的排错工具。先读最底部的异常类型和提示信息,再往上查找你自己的代码出错的地方。

7.2 常见问题与排查思路

问题现象可能原因排查方式解决方案
运行pip install django报错虚拟环境未激活或 pip 版本过旧检查终端当前环境,运行which python看是不是虚拟环境路径激活虚拟环境,或升级 pip:python -m pip install --upgrade pip
访问页面报 404URL 路由配置不对或 app 未挂载到总路由检查mysite/urls.py是否包含include('message.urls'),app 的urls.py是否有空路径匹配在项目总路由中正确添加include
表单提交报 403模板中缺少{% csrf_token %}检查表单 HTML 中是否包含 CSRF token<form>标签内加入{% csrf_token %}
页面提示Table 'message.Message' doesn't exist模型没有完成数据库迁移执行python manage.py makemigrationspython manage.py migrate将迁移结果提交到版本库,部署后执行migrate
修改了模型但数据库没变化忘记重新生成迁移文件依次执行makemigrationsmigrate每次模型变更都必须重新生成并执行迁移
8000 端口被占用有其他服务占用了该端口运行lsof -i :8000(macOS/Linux)或netstat -ano(Windows)查看改用其他端口:python manage.py runserver 8001
页面提示TemplateDoesNotExist模板文件路径不对或放错目录检查 app 目录下的templates结构确认模板位置在app/templates/app/index.html

7.3 部署前需要处理的隐患

如果你准备把项目部署到服务器,有几点必须注意:

  • settings.py中的DEBUG必须设为False,否则会暴露详细的错误堆栈信息,存在严重的安全风险。
  • ALLOWED_HOSTS必须配置为你的服务器域名或 IP。
  • SECRET_KEY不能使用默认值,且不能直接明文提交到公开仓库。
  • 使用真实部署方案(如 Gunicorn + Nginx)时,静态文件的收集需要执行python manage.py collectstatic

8. Django 学习的下一步:主线之外的扩展

当你跑通上面的留言板项目,你就已经掌握了 Django 的核心主线。接下来的学习应该围绕这条主线向外扩展,而不是跳到零散的知识点里。

建议按照下面的顺序继续深入:

8.1 深入 ORM 查询

目前只用到了all()create(),但这只是 ORM 能力的冰山一角。建议学习:

  • 过滤查询:Message.objects.filter(nickname='小明')
  • 排除查询:Message.objects.exclude(nickname='小明')
  • 排序查询:Message.objects.order_by('-created_at')
  • 聚合查询:Message.objects.count()
  • 关联查询:多表之间通过ForeignKeyManyToManyField建立关系

ORM 是 Django 中效率最高的部分之一。学会用 ORM 处理多表关系,你的数据建模能力会上一个台阶。

8.2 使用 Django 表单系统

上面的示例用了最原始的手写 HTML 表单和服务端手写校验。真实项目中更推荐使用 Django 的 Form 或 ModelForm 来管理表单,它能够自动完成数据校验、错误提示、CSRF 防护等工作。不过不建议在刚入门时就沉迷于表单的每一种写法,先把原生 HTML 表单跑通,再引入 Form 体系,理解会更扎实。

8.3 理解“类视图”和“通用视图”

Django 的视图可以写成函数,也可以写成类。类视图提供了ListViewDetailViewCreateView等通用视图,两行代码就能实现一个列表页。类视图的代码量看起来比函数视图少很多,但可读性对新手并不友好。我的建议是:先用函数视图建立心智模型,再看类视图时就会觉得“原来是封装了这些步骤”。不要在入门阶段强行使用类视图,否则很容易被继承关系绕晕。

8.4 引入 Django REST Framework

如果你将来打算做前后端分离,或者写 API 接口给小程序、App 使用,Django REST Framework(DRF)是绕不开的。DRF 基于 Django 提供了序列化、认证、权限、视图集、路由等一系列 API 开发工具。但学习 DRF 的前提是先把 Django 基础吃透,尤其是模型和查询这一块。

9. 给新手的最佳实践建议

最后总结几条学习 Django 的实用建议。这些建议来自很多人在项目中的实际踩坑经验,不是空话。

第一,每个新知识点都要跑通一个最小示例。不要只是“看懂了”就继续往下学。比如学完 ORM 的filter,就在自己的留言板项目里加一个“按昵称搜索”的功能页。知识只有用起来才是自己的。

第二,遇到异常先读堆栈信息。Django 的报错信息已经足够友好,会告诉你是哪个文件、哪一行、什么异常。新手最常见的坏习惯是把整个页面报错截图发群里问“怎么办”,而不先自己看一遍错误信息。自己读一遍,通常能解决八成问题。

第三,不要一上来就引入一堆第三方库。很多项目一开始只需要 Django 自带的 ORM、模板系统和 Admin,根本不需要 Celery、Redis、DRF 这些复杂组件。过度设计是新手学习路上的重灾区。

第四,用 Git 管理代码。从第一个可运行版本开始,就建立 Git 仓库并逐步提交。这样你可以在做实验的时候大胆改代码,出错之后可以随时回滚。部署时间也避免了“我这个能跑,为什么他那里不能跑”的尴尬。

第五,控制学习节奏,别贪多。Django 生态非常庞大,每年都有新的第三方包出现。但对于新手来说,先把最核心的 MVT 链路、ORM 基础、模板语法、表单流程吃透,就已经具备了独立开发小型 Web 应用的能力。其他的内容,等需求来了再学完全来得及。

这篇文中的留言板项目代码量很小,但它把 Django 最核心的请求链路完整展示了一遍。我建议你亲手敲一遍,而不是复制粘贴。敲代码的过程中犯几个错,再自己排掉,效果比看十遍教程都好。当你把这条主线跑顺,再回头看官方文档,会发现自己已经能轻松理解大部分内容了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询