尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Django入门:理清MVT与请求生命周期,从零搭建留言板

Django入门:理清MVT与请求生命周期,从零搭建留言板 很多新手学 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。很多新手第一次看到这三个词会和传统 MVCModel-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.py、views.py、urls.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.py、views.py、admin.py、migrations/等文件。在 Django 中一个 app 就是一个可复用的业务模块你可以把它理解成一个“功能包”。这里不深入讨论 app 和项目的区别只需要知道项目是网站的配置容器app 是具体的业务代码。创建完 app 之后要在mysite/settings.py的INSTALLED_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_length50, verbose_name昵称) content models.TextField(verbose_name留言内容) created_at models.DateTimeField(auto_now_addTrue, 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_addTrue表示创建记录时自动填充当前时间。Meta类里的ordering [-created_at]让查询结果默认按创建时间倒序这样最新留言排在前面。__str__方法决定了这条记录在 Admin 后台和在调试时的展示形式。4.3 生成并执行数据库迁移模型定义之后需要把它“翻译”成数据库表。这一步在 Django 里叫迁移migration。python manage.py makemigrations python manage.py migratemakemigrations会根据模型变化生成迁移文件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, nameindex), ]然后再在项目的总路由文件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)), ]这里用include把message应用的路由挂载到项目根路径下。以后每次新增一个功能模块只需要在 app 内部维护自己的urls.py项目的总路由保持整洁。4.6 创建模板文件Django 默认会到每个 app 下面的templates目录里找模板文件。创建message/templates/message/index.html!-- message/templates/message/index.html -- !DOCTYPE html html langzh-CN head meta charsetUTF-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 langzh-CN head meta charsetUTF-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 methodpost action{% url index %} {% csrf_token %} p label昵称/label input typetext namenickname required /p p label内容/label textarea namecontent required/textarea /p button typesubmit提交/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(nicknamenickname, contentcontent) 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看是不是虚拟环境路径激活虚拟环境或升级 pippython -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 doesnt exist模型没有完成数据库迁移执行python manage.py makemigrations和python manage.py migrate将迁移结果提交到版本库部署后执行migrate修改了模型但数据库没变化忘记重新生成迁移文件依次执行makemigrations和migrate每次模型变更都必须重新生成并执行迁移8000 端口被占用有其他服务占用了该端口运行lsof -i :8000macOS/Linux或netstat -anoWindows查看改用其他端口python manage.py runserver 8001页面提示TemplateDoesNotExist模板文件路径不对或放错目录检查 app 目录下的templates结构确认模板位置在app/templates/app/index.html7.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()关联查询多表之间通过ForeignKey、ManyToManyField建立关系ORM 是 Django 中效率最高的部分之一。学会用 ORM 处理多表关系你的数据建模能力会上一个台阶。8.2 使用 Django 表单系统上面的示例用了最原始的手写 HTML 表单和服务端手写校验。真实项目中更推荐使用 Django 的 Form 或 ModelForm 来管理表单它能够自动完成数据校验、错误提示、CSRF 防护等工作。不过不建议在刚入门时就沉迷于表单的每一种写法先把原生 HTML 表单跑通再引入 Form 体系理解会更扎实。8.3 理解“类视图”和“通用视图”Django 的视图可以写成函数也可以写成类。类视图提供了ListView、DetailView、CreateView等通用视图两行代码就能实现一个列表页。类视图的代码量看起来比函数视图少很多但可读性对新手并不友好。我的建议是先用函数视图建立心智模型再看类视图时就会觉得“原来是封装了这些步骤”。不要在入门阶段强行使用类视图否则很容易被继承关系绕晕。8.4 引入 Django REST Framework如果你将来打算做前后端分离或者写 API 接口给小程序、App 使用Django REST FrameworkDRF是绕不开的。DRF 基于 Django 提供了序列化、认证、权限、视图集、路由等一系列 API 开发工具。但学习 DRF 的前提是先把 Django 基础吃透尤其是模型和查询这一块。9. 给新手的最佳实践建议最后总结几条学习 Django 的实用建议。这些建议来自很多人在项目中的实际踩坑经验不是空话。第一每个新知识点都要跑通一个最小示例。不要只是“看懂了”就继续往下学。比如学完 ORM 的filter就在自己的留言板项目里加一个“按昵称搜索”的功能页。知识只有用起来才是自己的。第二遇到异常先读堆栈信息。Django 的报错信息已经足够友好会告诉你是哪个文件、哪一行、什么异常。新手最常见的坏习惯是把整个页面报错截图发群里问“怎么办”而不先自己看一遍错误信息。自己读一遍通常能解决八成问题。第三不要一上来就引入一堆第三方库。很多项目一开始只需要 Django 自带的 ORM、模板系统和 Admin根本不需要 Celery、Redis、DRF 这些复杂组件。过度设计是新手学习路上的重灾区。第四用 Git 管理代码。从第一个可运行版本开始就建立 Git 仓库并逐步提交。这样你可以在做实验的时候大胆改代码出错之后可以随时回滚。部署时间也避免了“我这个能跑为什么他那里不能跑”的尴尬。第五控制学习节奏别贪多。Django 生态非常庞大每年都有新的第三方包出现。但对于新手来说先把最核心的 MVT 链路、ORM 基础、模板语法、表单流程吃透就已经具备了独立开发小型 Web 应用的能力。其他的内容等需求来了再学完全来得及。这篇文中的留言板项目代码量很小但它把 Django 最核心的请求链路完整展示了一遍。我建议你亲手敲一遍而不是复制粘贴。敲代码的过程中犯几个错再自己排掉效果比看十遍教程都好。当你把这条主线跑顺再回头看官方文档会发现自己已经能轻松理解大部分内容了。
返回列表