很多人学 Django 的方式,是先花两周看完一套教程,再打开 IDE 准备做第一个项目,结果发现无从下手。这不是你笨,而是大多数教程把 Django 拆成了互不相干的知识点:模型讲一遍、视图讲一遍、模板讲一遍、路由讲一遍,每个知识点单独看都懂,放到真实项目里却不知道它们怎么咬合在一起。真正的问题不是代码量不够,而是缺少对 Django 运行流程的整体直觉。
这篇是这个系列的第一部分,目标是用最少的步骤把一个真实的 Django Web 应用跑起来,并且让你理解一个 HTTP 请求从浏览器发出之后,到底经过了哪些环节,最后才变成你看到的页面。读完以后,你应该能独立完成:环境搭建、创建项目、创建应用、编写视图、配置路由、渲染模板、配置数据库,以及使用 Django 自带的管理后台维护数据。这一套流程跑通之后,后面再学表单、认证、类视图、部署,都是在已有骨架上填肉,而不是重新学一遍。
本文不打算把所有 Django 语法都讲一遍,而是聚焦"构建真实 Web 应用"这条主线。每一节会说明这一步在实际项目中解决什么问题,不做什么,容易错在哪里。如果你正在找一种能帮你从"会看教程"过渡到"会做项目"的学习路径,这篇文章值得你读完并收藏。
1. 这篇文章真正要解决的问题
先交代一下这篇文章的判断:Django 真正值得学的不是它有多少内置函数,而是一整套 Web 开发方法论。很多人学了很久 Django,遇到真实需求还是不会下手,是因为一直停留在"照着教程敲代码"的层面,没有建立起属于自己的项目骨架。
1.1 为什么大多数 Django 学习者卡在中途
我观察到三个典型现象。
第一,以知识点为中心的学习方式。今天学 QuerySet 的各种查询方法,明天学模板标签,好像每个知识点都学了,但遇到一个"从数据库取出文章列表并显示在页面上"的需求时,不知道代码该写在哪个文件、先写模型还是先写视图。
第二,不知道每一步解决什么问题。跟着教程能跑通,但换了项目、换了页面,就不知道如何扩展。因为教程只告诉你"这样做",没告诉你"为什么必须这样做"。
第三,缺乏 HTTP 请求到响应的完整心智模型。Web 框架的本质是处理 HTTP 请求:浏览器发来请求,框架里的某个函数处理这个请求,返回一个响应。如果你不理解这条链路,那么模型、视图、模板、URL 配置这些概念永远是一堆碎片。
1.2 这个系列的学习路径
这是一套四部分内容中的第一部分。本部分解决的是"骨架"问题:把 Django 项目的三层结构——请求入口(URL)、业务逻辑(View)、数据模型(Model)——完整地建立起来。后续部分会在这个基础上继续深入更真实的功能开发。
在开始之前,建议你确认一件事:你已经掌握了 Python 的基本语法,包括函数、类、列表和字典。如果你对 Python 还很陌生,建议先回头熟悉一下 Python 基础再开始 Django,否则你可能分不清一个报错是 Python 语法问题还是 Django 框架问题。
1.3 读完这篇文章你能获得什么
- 一套能复用的 Django 项目创建流程,而不是死记命令。
- 对 MTV 架构下请求处理链路的具体认知,而不是停留在概念层面。
- 一个带数据库模型和管理后台的最小真实应用,可以在浏览器里增删改查数据。
如果你能跟着文章完整操作一遍,那么你学 Django 的第一块基石就稳了。
2. Django核心概念:框架、MTV架构与适用场景
2.1 Django到底是什么
Django 是一个用 Python 编写的 Web 框架。所谓 Web 框架,就是帮开发者处理 Web 开发中大量重复工作的工具集。如果没有框架,你需要自己处理:如何接收 HTTP 请求、如何从请求里取出参数、如何判断请求该交给哪段代码、如何拼接 HTML、如何操作数据库、如何防御常见的 Web 攻击。
Django 的做法是"自带电池"(batteries included)。官方把 Web 开发中常见的功能都内置好了:ORM 数据库映射、模板系统、表单处理、用户认证、Admin 管理后台、CSRF 防护、Session 管理等等。好处是你在项目初期不需要到处找第三方库,也能把一个功能完整的产品做出来。坏处是框架本身比较大,刚开始学的时候会觉得"东西太多"。
这个特性决定了它的定位:适合做内容型、管理型、数据型的 Web 应用,而不是追求极致轻量或极致性能的边缘场景。
2.2 MTV架构:Django处理请求的方式
很多人听说过 MVC(Model-View-Controller),Django 的架构在思想上与 MVC 一致,但官方喜欢用 MTV 来描述:
| 角色 | 职责 | 对应目录或文件 |
|---|---|---|
| Model | 数据模型,与数据库表对应 | models.py |
| Template | 页面模板,负责展示数据 | templates/ 目录下的 html 文件 |
| View | 业务逻辑,接收请求、处理数据、返回响应 | views.py |
| URL 配置 | 路由,决定哪个 URL 交给哪个 View 处理 | urls.py |
一个请求从浏览器发起到页面渲染的完整流程是:
- 浏览器发起 http://127.0.0.1:8000/ 请求。
- Django 根据项目根路由 urls.py 找到该 URL 对应的 View 函数。
- View 函数执行业务逻辑,比如通过 Model 从数据库读取文章列表。
- View 把数据放入一个上下文(context)字典,交给 Template。
- Template 渲染出最终 HTML,返回给浏览器。
很多人学 Django 最大的误区是试图按照 MVC 的 controller 概念去找对应文件。在 Django 里,View 既是控制器也是视图,你只需要记住:View 是 Django 应用的大脑,Model 是数据底座,Template 是展示层,URL 是入口。这个心智模型一旦建立,后面学什么都快。
2.3 Django适合做什么,不适合做什么
适合做的场景:
- 内容管理系统,比如博客、新闻站、企业官网后台。
- 企业内部管理系统,比如运营后台、CRM、数据管理平台。
- 电商系统和 SaaS 产品的 MVP 版本。
- 带管理后台的 Python 后端服务。
不适合做的场景:
- 极端高并发的实时应用,比如一个连接百万用户的 WebSocket 网关,Django 能支持但你需要额外做很多架构工作,选择 Go 或 Node.js 也许更直接。
- 只需要一个轻量 API、对性能要求极高的服务,FastAPI 这类异步框架更合适。
但要注意,不适合不等于不能做。Django 配合 Django REST Framework,同样可以构建高质量的后端 API,只是你要理解它的应用边界在哪里。实际项目选型时,团队熟悉哪种技术、项目需求是数据管理还是实时计算、交付周期是多长,这些因素比"哪个框架更强"更重要。
3. 环境准备:Python、虚拟环境与Django安装
进入实操部分。本文示例基于 Python 3.x 和 Django 5.x,具体版本请以你安装时的官方信息为准。下面这套流程在 Windows、macOS、Linux 上都能执行,差别只在激活虚拟环境的命令。
3.1 检查Python环境
在终端中执行:
python --version如果你的系统同时安装了 Python 2 和 Python 3,可能需要使用:
python3 --version如果提示找不到命令,需要先去 Python 官网下载安装。安装时注意勾选“Add Python to PATH”,这一步能避免后面出现“python 不是内部或外部命令”的报错。
Django 5.x 对 Python 版本有要求,一般建议 Python 3.10 或更高版本。如果你的 Python 版本过低,安装最新版 Django 时会提示版本不支持。
3.2 创建虚拟环境
虚拟环境的主要作用是隔离不同项目的依赖。假设你同时维护多个 Python 项目,一个项目用 Django 4,另一个项目用 Django 5,没有虚拟环境时,后安装的版本会覆盖前一个,导致项目无法运行。虚拟环境为每个项目创建独立的依赖空间。
在项目目录下执行:
python -m venv venv这会在当前目录生成一个 venv 文件夹,里面保存了该项目的独立 Python 解释器和库。
激活虚拟环境:
# macOS / Linux source venv/bin/activate # Windows venv\Scripts\activate激活后,终端行首会出现(venv)标记。Windows 系统如果遇到“禁止运行脚本”的提示,需要用管理员权限打开 PowerShell 执行Set-ExecutionPolicy RemoteSigned调整执行策略,或者改用 CMD 运行。
3.3 安装Django
确认虚拟环境已激活后,执行:
pip install django如果想安装指定版本:
pip install django==5.1.3安装完成后,用 pip show 验证:
pip show django也可以进入 Python 交互环境验证:
import django print(django.get_version())输出版本号说明安装成功。从这一步开始,后续所有命令都要在虚拟环境激活的状态下执行。如果你关闭终端,重新打开后忘记激活虚拟环境,会发现 django-admin 命令又消失了。
3.4 选择编辑器
推荐使用 VS Code 或 PyCharm。VS Code 用户需要安装 Python 扩展,然后用 Ctrl+Shift+P 打开命令面板,执行“Python: Select Interpreter”,选择刚才创建的 venv 目录下的解释器。这一步很关键,如果解释器选错,VS Code 会提示找不到 Django。
常见现象:终端里明明安装了 Django,编辑器里却提示 No module named 'django',99% 是解释器没有指向当前项目的虚拟环境。
4. 创建Django项目与应用:项目和应用的区别
4.1 创建项目
在虚拟环境激活状态下,执行:
django-admin startproject myblog cd myblog这里的 myblog 是项目名称。执行后生成的项目结构如下:
myblog/ ├── manage.py └── myblog/ ├── __init__.py ├── settings.py ├── urls.py ├── asgi.py └── wsgi.py各文件作用:
- manage.py:项目管理入口。运行开发服务器、执行数据库迁移、创建应用,都是通过它执行。
- settings.py:项目配置文件。数据库、应用注册、模板路径、静态文件等都在这里配置。
- urls.py:项目根路由。所有 URL 的分发入口。
- asgi.py / wsgi.py:部署到服务器时的入口文件。
先运行开发服务器试试:
python manage.py runserver启动后访问 http://127.0.0.1:8000/ ,看到 Django 默认欢迎页说明项目创建成功。这个页面确认了 Django 的开发服务器能正常工作。
4.2 创建应用
接下来创建 App。Django 项目是一个容器,一个项目里可以有多个应用,每个应用负责一个独立业务模块。比如一个内容系统可以有 article(文章)、user(用户)、comment(评论)三个应用。
python manage.py startapp article执行后生成的目录:
article/ ├── migrations/ ├── __init__.py ├── admin.py ├── apps.py ├── models.py ├── tests.py └── views.py新手最容易混淆项目和应用。项目是整体配置环境,应用是具体业务实现。一个项目可以包含多个应用,一个应用也可以被多个项目复用。把不同业务拆到不同应用里,是 Django 项目保持可维护性的关键。
4.3 将应用注册到项目
创建应用后,需要把它注册到 settings.py 的 INSTALLED_APPS 列表里。打开 myblog/settings.py:
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'article', # 新增 ]如果没有这一步,Django 不会识别这个应用,后面执行迁移时也检测不到 article 应用的模型。
注册后执行一次内置迁移:
python manage.py migrate这条命令会根据 Django 内置应用的迁移文件创建数据库表,包括用户表、Session 表、Admin 相关表等。执行成功后,项目里已经存在一个默认的 SQLite 数据库文件 db.sqlite3。
顺便把语言和时区改为中文,方便后续使用管理后台。修改 settings.py:
LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai'改完后重新运行服务器,管理后台会显示中文界面。
5. 视图、URL配置与模板:让页面真正跑起来
现在开始写业务代码。一个 Django 页面需要三个要素:视图函数(处理逻辑)、URL 配置(路由映射)、模板(页面渲染)。我们会一步步把它们组装起来。
5.1 第一个视图函数
打开 article/views.py,写一个最简单的视图:
from django.http import HttpResponse def index(request): return HttpResponse("Hello, Django!")再创建 article/urls.py,配置 URL 与该视图的映射关系:
from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), ]最后修改项目根路由 myblog/urls.py,把 article 应用的 URL 配置包含进来:
from django.contrib import admin from django.urls import include, path urlpatterns = [ path('admin/', admin.site.urls), path('', include('article.urls')), ]保存后访问首页,你会看到页面上显示“Hello, Django!”。这个流程虽然简单,但它验证了整条链路:请求进入了 article.urls,找到了 index 视图,视图返回了一个响应。
这里有一个新手常见错误:写了 article/urls.py,但在项目 urls.py 里忘了用 include 引入,结果访问页面时永远 404。URL 配置的顺序很重要:Django 从上到下匹配,遇到第一个匹配的 URL 就停止。
5.2 用模板渲染HTML
返回纯文字不算真实页面。模板系统解决的是“如何生成动态 HTML”。在 article 应用下创建 templates/article/index.html:
<!DOCTYPE html> <html lang="zh-hans"> <head> <meta charset="UTF-8"> <title>文章首页</title> </head> <body> <h1>文章列表</h1> <p>{{ message }}</p> </body> </html>修改 views.py:
from django.shortcuts import render def index(request): context = { 'message': '欢迎来到 Django 真实项目实战', } return render(request, 'article/index.html', context)刷新页面,看到“欢迎来到 Django 真实项目实战”,说明模板渲染成功。render 函数的第一个参数是请求对象,第二个参数是模板路径,第三个参数是 context 字典,模板中可以通过{{ message }}使用字典中的值。
Django 会自动到每个已注册应用的 templates 目录下查找模板,不用手动指定绝对路径。模板文件名里的article/前缀是为了避免不同应用下有同名模板文件时互相覆盖。
5.3 模板变量与循环
真实页面通常要展示列表数据。在 views.py 中传入一个列表:
def index(request): articles = [ {'id': 1, 'title': 'Django 入门', 'author': '张三'}, {'id': 2, 'title': 'Python 进阶', 'author': '李四'}, ] context = { 'articles': articles, 'page_title': '文章列表', } return render(request, 'article/index.html', context)在模板中遍历这个列表:
<h1>{{ page_title }}</h1> <ul> {% for article in articles %} <li>{{ article.title }} - {{ article.author }}</li> {% endfor %} </ul>Django 模板语言只有两种主要语法:
{{ variable }}:输出变量的值。{% tag %}:执行逻辑,如 for 循环、if 判断。
模板不是 Python,它刻意限制了逻辑能力,目的是让页面展示代码保持简单。不要在模板里写复杂业务逻辑,业务逻辑应该放在视图里。
5.4 静态文件与样式
页面还需要 CSS、JS、图片这类静态文件。Django 的开发服务器会通过 StaticFilesFinder 查找静态文件。在 article 应用下创建 static/article/style.css:
body { font-family: "Microsoft YaHei", sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; } h1 { color: #2c3e50; }在模板头部加载静态文件:
{% load static %} <!DOCTYPE html> <html lang="zh-hans"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="{% static 'article/style.css' %}"> <title>文章首页</title> </head>开发阶段 Django 能直接处理静态文件,但部署到服务器后,静态文件通常交给 Nginx 等 Web 服务器托管,Django 本身不负责高性能地提供静态文件。这个差异要在部署时特别注意。
6. 数据库模型与管理后台:真实应用的数据底座
前面列表数据是写死在视图里的,真实项目的数据要存到数据库。Django 用 ORM(对象关系映射)来操作数据库:你定义 Python 类,Django 自动创建对应的数据库表,查询、新增、修改、删除都通过 Python 对象完成,不需要写原生 SQL。
6.1 定义模型
打开 article/models.py,定义一个文章模型:
from django.db import models class Article(models.Model): title = models.CharField(max_length=200) author = models.CharField(max_length=50) content = models.TextField() created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return self.title字段说明:
- CharField:短文本字段,适合标题、作者名,必须指定 max_length。
- TextField:长文本字段,适合文章正文。
- DateTimeField:日期时间字段,auto_now_add=True 表示创建记录时自动写入当前时间。
__str__方法是给 Django 后台用的,显示对象时返回文章标题。
这段代码定义的是“数据模型”,还不能直接操作数据库。要让 Django 知道模型变化,需要两步:先生成迁移文件,再执行迁移。
6.2 生成迁移并执行
python manage.py makemigrations article python manage.py migratemakemigrations 做的事情是“把模型的变化记录成迁移脚本”,migrate 才是“真正把脚本执行到数据库”。第一次接触时容易把这两步混在一起。如果你修改了模型,一定要重新执行 makemigrations,否则数据库不会感知到变化。
执行成功后,models 里的 Article 类就在数据库里对应了一张 article_article 表。
6.3 注册模型到管理后台
Django Admin 是它最受欢迎的功能之一。只要把模型注册到 admin.py,就能得到一个可用的后台管理界面,不需要自己写页面。
修改 article/admin.py:
from django.contrib import admin from .models import Article admin.site.register(Article)创建超级管理员账号:
python manage.py createsuperuser按提示输入用户名、邮箱、密码。密码输入时不会显示,这是正常现象。Django 有密码复杂度要求,如果提示太弱,换一个包含字母和数字的长密码。
然后访问 http://127.0.0.1:8000/admin/ ,使用刚创建的账号登录。你会看到“文章”的增删改查界面,可以点击“增加”创建一篇真实文章。这一步很重要,因为之后首页的列表数据将来自这里,而不是写死在代码里的列表。
6.4 在视图中使用数据库数据
修改 views.py,把写死的列表换成从数据库查询:
from django.shortcuts import render from .models import Article def index(request): articles = Article.objects.all().order_by('-created_at') context = { 'articles': articles, 'page_title': '文章列表', } return render(request, 'article/index.html', context)Article.objects.all() 查询所有文章记录,order_by('-created_at') 按创建时间倒序排列。在后台添加几篇文章,回到首页刷新,你会看到刚添加的文章自动出现在页面上。
到这里,一个最小可用的 Django 数据流闭环形成了:后台写入数据 → 数据库存储 → 视图查询 → 模板展示。这个闭环就是绝大多数内容型 Web 应用的核心骨架。
6.5 数据库配置说明
默认情况下,Django 使用 SQLite,你不需要安装任何额外的数据库服务。对于入门和中小规模项目,SQLite 够用且零维护成本。
真实项目中更常用 MySQL 或 PostgreSQL。切换数据库只需要修改 settings.py 中的 DATABASES 配置,代码里的 ORM 查询基本不用改。这是 Django ORM 带来的好处。但要注意,切换数据库涉及数据库驱动安装和连接参数,属于部署阶段的工作,建议在测试环境验证后再操作,操作前备份数据。
7. 常见问题与排查思路
下面是初学者最常见的问题和排查方法。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 运行 runserver 提示端口被占用 | 8000 端口已被其他进程使用 | 看报错信息中的端口号 | python manage.py runserver 8080换端口 |
| 访问页面一直 404 | App 没有注册或路由器没有 include | 检查 settings.py INSTALLED_APPS 和项目 urls.py | 注册 App,并用 include 引入子路由 |
| 提示 No module named 'django' | 当前 Python 环境不是虚拟环境 | 终端执行which python或where python | 激活虚拟环境后重新安装依赖 |
| 提示 No module named 'article' | 应用目录不在项目可导入路径下 | 检查 article 目录是否存在__init__.py | 用 startapp 重新创建,不要手动乱建目录 |
| 执行 makemigrations 没有生成文件 | App 未注册到 INSTALLED_APPS | 检查 settings.py | 注册 App 后重新执行 |
| 迁移时报 No migrations to apply | 数据库已有对应表,或迁移文件状态异常 | 检查应用 migrations 目录与数据库表 | 在测试环境中重建数据库再迁移 |
| 模板中变量显示为空 | context 键名与模板变量名不一致 | 对比视图 context 与模板 {{ }} 的名称 | 统一变量名 |
| 页面中文乱码 | 文件编码或数据库字符集问题 | 确认模板<meta charset="UTF-8">,环境变量 | 统一使用 UTF-8 编码 |
| 后台登录提示密码太弱 | Django 默认密码策略要求复杂度 | 按提示调整密码 | 使用至少 8 位、包含字母和数字的密码 |
| 修改模型后数据库无变化 | 忘记执行生成迁移和迁移 | 执行 makemigrations + migrate | 每次修改模型后都要执行这两步 |
遇到问题时,一个先后的排查顺序是:先看终端命令行有没有报错,再看 Django 调试页面提示的异常位置,最后检查 settings.py 和 urls.py 这两个最容易出错的配置文件。
8. 最佳实践与工程建议
到这里,你已经跑通了一个带数据库的 Django 应用。接下来是在真实项目中需要养成的工程习惯。
8.1 项目结构
- 一个项目不要只放一个应用。按业务边界拆分,比如 article、user、comment 分开。
- 应用命名使用单数名词,比如 ArticleApp 没有必要,直接叫 article。
- 模板文件在应用下加一层与应用同名的子目录,防止多个应用模板互相覆盖。
8.2 配置管理
- 不要把数据库密码、SECRET_KEY 等敏感信息硬编码在 settings.py 里,通过环境变量读取。
- SECRET_KEY 是 Django 进行加密签名的基础密钥,泄露后可能导致 Session 伪造,生产环境必须设为随机值。
- 生产环境必须关闭 DEBUG。DEBUG=True 时,Django 会输出详细异常页面,泄露代码路径和配置信息,非常危险。
8.3 数据库与迁移
- 每次修改模型,都要生成迁移文件并提交到版本控制,不要把迁移文件随意删除。
- 生产环境执行迁移前,先备份数据库,并在测试环境验证迁移脚本。
- 不要在生产环境直接运行 migrate 而不检查迁移顺序。多人协作时,迁移文件冲突要用 merge 方案解决。
8.4 安全习惯
- Admin 后台是管理系统的入口,账号必须使用强密码。
- 可以修改 admin 后台的 URL 路径,降低被扫描工具探测到的概率。做法很简单,在项目 urls.py 里把 path('admin/', ...) 改成不明显的路径。
- Django 内置了 CSRF 防护、XSS 转义、SQL 注入防护,使用内置功能时不要试图关闭这些中间件。
8.5 依赖锁定
一个项目应该有独立的 requirements.txt,固定依赖版本。在虚拟环境中执行:
pip freeze > requirements.txt后面换机器或部署时,执行:
pip install -r requirements.txt这样能保证依赖环境一致,避免出现“本地能跑,部署到服务器跑不了”的问题。
9. 总结与后续学习方向
第一部分到这里就结束了。你现在已经完成了一个真实 Django 应用的骨架搭建:创建了项目和应用,理解了 MTV 架构,体验了从 URL 到视图再到模板的完整请求链路,并且通过定义模型、执行迁移、注册 Admin,让数据在后台和前端之间真正流动起来。
这个骨架的核心价值在于,你已经知道一个 Django 项目的基本组成,后面学习任何新知识点都有地方安放。学表单时,你知道它服务于视图;学认证时,你知道它是模型层和视图层之间的协作;学部署时,你知道这些问题都属于配置和运维层面。
接下来的实践方向建议按顺序进行:
- 给 Article 模型增加分类和标签字段,扩展数据关联关系。
- 做一个文章详情页,学会从数据库中获取单条记录并处理 404。
- 学习 Django 内置表单,实现通过前台页面提交文章。
- 学习基于类的视图,减少重复代码。
- 了解 Django REST Framework,为前端或其他系统提供 JSON API。
- 最后再学习 Nginx、Gunicorn 与 Django 的部署组合。
很多人在学会创建项目之后,会急着学更多高级功能。但这里我更建议你先把当前的模型、视图、模板、Admin 这条链路多加练习,用自己的业务场景把它改造一遍。比如做一个图书管理、笔记管理、日程管理的小应用,把后台添加的数据展示到前台。做通一个,再学下一个,比一次性学完所有功能更有效。
下一篇教程会继续推进这个项目,把静态首页变成真正可以承载内容的系统,包括详情页、列表筛选和分页。你可以先把当前骨架跑熟,准备进入下一阶段。