作者:IT策士
10余年一线大厂经验,专注 IT 思维、架构、职场进阶。我会在公众号、今日头条持续发布最新文章,助你少走弯路。
无论你是刚跨入 Web 开发大门的新手,还是想从其他框架迁移过来的进阶开发者,理解 Django 的“骨架”和“灵魂”都是绕不开的第一步。本文不会只丢给你一堆命令和概念,而是通过环境搭建-> Hello World -> 项目结构剖析 -> MTV 实战 这一条线,部署和可亲手验证的例子,带你深入浅出地吃透 Django 的启动原理。
读完你会获得:
-
可运行的最小 Django 项目
-
对项目结构每个文件的清晰认知
-
通过控制台打印理解 Django 请求生命周期
-
MTV 模式下的模型建立、视图渲染、模板展示的全流程
1. 环境准备:搭建干净的 Python 舞台
1.1 确认 Python 版本
Django 4.2 LTS 需要 Python 3.8+,Django 5.0+ 要求 Python 3.10+。打开终端执行:
$ python3 --version
Python 3.12.3
如果你的系统同时存在 Python 2,请始终使用 python3 和 pip3 命令。
1.2 创建虚拟环境
虚拟环境能隔离项目依赖,避免污染全局 Python。在项目父目录下:
$ python3 -m venv django_env
$ source django_env/bin/activate # Linux/macOS
# 或 Windows 下: django_env\Scripts\activate
激活成功后,终端提示符前会出现 (django_env) 标识。控制台输出类似:
(django_env) user@host:~/projects$
1.3 安装 Django 并验证
(django_env) $ pip install django
Collecting django
Downloading Django-4.2.11-py3-none-any.whl (8.1 MB)
...
Successfully installed asgiref-3.8.1 django-4.2.11 sqlparse-0.5.0
(django_env) $ python -m django --version
4.2.11
看到版本号即为安装成功。至此环境准备完毕。
2. 第一个 Django 项目:从零到“火箭”
2.1 创建项目
使用 django-admin startproject 命令,我们创建一个名为 mysite 的项目:
(django_env) $ django-admin startproject mysite
(django_env) $ cd mysite
(django_env) $ ls
manage.py mysite/
控制台没有任何输出是正常的 —— Django 会默默生成一套初始文件。我们来看目录树:
mysite/
├── manage.py
└── mysite/
├── __init__.py
├── settings.py
├── urls.py
├── asgi.py
└── wsgi.py
2.2 运行开发服务器,看见欢迎页
Django 自带轻量级开发服务器,绝对不要用于生产环境。执行:
(django_env) $ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
May 13, 2026 - 10:23:45
Django version 4.2.11, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
打开浏览器访问 http://127.0.0.1:8000/,你会看到 Django 的“小火箭”欢迎页。此时控制台会输出访问日志:
[13/May/2026 10:24:01] "GET / HTTP/1.1" 200 16364
这个页面是 django.views.debug 默认提供的,说明项目骨架已能正常响应请求。在没有添加任何视图时,Django 的 URL 配置会引导到这个调试页面。
现在,我们要让它输出我们自己的 “Hello, World”。
3. 第一个应用与 Hello World:让控制台开口说话
Django 哲学是:一个“项目”可以包含多个“应用”。我们把业务逻辑放在应用里。
3.1 创建应用
(django_env) $ python manage.py startapp hello
控制台同样无输出,但目录下多了一个 hello/ 文件夹:
hello/
├── __init__.py
├── admin.py
├── apps.py
├── migrations/
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
3.2 编写视图:让函数返回文字,并向控制台打印
打开 hello/views.py,写入:
from django.http import HttpResponse
from datetime import datetime
def say_hello(request):
# 这行会打印到运行服务器的终端上
print(f"[{datetime.now()}] say_hello 视图被访问了!")
return HttpResponse("Hello, World! 你好,世界!")
print 正是我们观察请求时机的最直接方式。
3.3 配置 URL 映射
光有视图不行,必须告诉 Django 什么路径对应什么视图。在 hello/ 目录下新建 urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.say_hello, name='hello'),
]
然后修改项目总路由 mysite/urls.py,将 hello 应用的路由包含进来:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', include('hello.urls')), # 新增
]
3.4 注册应用(重要)
Django 需要知道有哪些应用,这样它才能找到模板、静态文件等。编辑 mysite/settings.py,在 INSTALLED_APPS 列表中添加:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
...
'hello', # 注册我们的应用
]
3.5 启动服务器,见证 Hello World
重新运行服务器(如果之前没停,它会自动重载):
(django_env) $ python manage.py runserver
浏览器访问 http://127.0.0.1:8000/hello/,页面显示:
同时,控制台会打印:
[2026-05-13 10:30:15] say_hello 视图被访问了!
[13/May/2026 10:30:15] "GET /hello/ HTTP/1.1" 200 30
进阶点:这里的
logging模块。
这样,我们就有了第一个会说话的 Hello World。更重要的是,你看到了 请求 → 路由 → 视图 的链路,控制台打印就是这链路的心跳。
4. 项目结构深度解剖:每个文件都在干什么?
新手往往会被一堆 .py 文件吓到,下面我们把它们拆开揉碎。结合“初始化 + 运行”的控制台输出,你会理解每个文件的存在意义。
4.1 manage.py:项目的管家
$ cat manage.py
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(...)
execute_from_command_line(sys.argv)
它做的事:设置环境变量DJANGO_SETTINGS_MODULE,指向 mysite.settings,然后把命令行参数交给 Django 的命令执行器。我们常用的 runserver、startapp、migrate、shell 都是由此进入。
你运行的 python manage.py runserver 之所以能启动服务器,就是因为它加载了 mysite.settings 中的配置(包括已安装应用、中间件等)。
4.2 项目配置包 mysite/
__init__.py
空文件,告诉 Python 这个目录是一个包。通常不需要动它。
settings.py —— 项目的控制中心
打开这个文件,关键部分:
BASE_DIR = Path(__file__).resolve().parent.parent # 项目根目录
SECRET_KEY = 'django-insecure-xxxx' # 密钥,加密签名用,绝对要保密
DEBUG = True # 开发模式,提供详细错误页面,生产环境必须 False
ALLOWED_HOSTS = [] # 允许访问的主机名,生产需配置
INSTALLED_APPS = [...] # 所有安装的应用
MIDDLEWARE = [...] # 中间件栈,处理请求/响应的钩子
ROOT_URLCONF = 'mysite.urls' # 根 URL 配置
TEMPLATES = [...] # 模板引擎配置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', ... } } # 数据库
控制台相关:当你运行 runserver 时,终端会输出:
Django version 4.2.11, using settings 'mysite.settings'
这印证了 manage.py 所设的环境变量。
urls.py —— 请求的交通指挥
前文我们已经修改过它。初始内容通常只有 admin/ 路由。每个 path() 将 URL 模式映射到一个视图函数。这里的“include”机制允许层层分发,形成树状路由结构,特别适合大型项目。
wsgi.py 和 asgi.py —— 通往生产环境的门
-
WSGI(Web Server Gateway Interface):同步接口,传统部署使用(如 Gunicorn + Nginx)。
-
ASGI(Asynchronous Server Gateway Interface):异步接口,支持 WebSocket、长连接。
我们使用的 runserver 开发服务器,其实就是启动了一个简单的 WSGI(或 ASGI)服务器。你可以通过 python manage.py runserver 的控制台输出看到协议类型(默认 WSGI,如果安装了异步支持可能切换)。通常这些文件不需要改动,除非要自定义应用加载。
4.3 应用结构 hello/
每个应用是一个可复用的模块:
-
views.py:存放视图函数或类,处理请求并返回响应。我们已经在这里放了say_hello。 -
models.py:定义数据模型(表结构),这是我们接下来要玩的重点。 -
admin.py:注册模型到 Django 自带的管理后台。 -
apps.py:应用配置,可在settings的INSTALLED_APPS中使用'hello.apps.HelloConfig'这种完整的路径。 -
migrations/:存放数据库迁移文件。每当你修改模型并执行makemigrations,Django 会在这里生成 Python 脚本,记录数据库变更。 -
tests.py:单元测试。建议一写应用就写好测试。
理解了结构,我们就可以深入 MTV 模式,让程序不只是返回字符串,而是动态地从数据库取数据并渲染漂亮页面。
5. MTV 模式深入剖析:模型、模板、视图的协奏曲
Django 常被归类为“MVC”框架,但它自己称为 MTV:
-
Model:数据存取层,处理数据库和业务规则。
-
Template:表现层,决定数据如何展示。
-
View:业务逻辑层,接收请求,处理数据,调用模板返回响应。
URL 分发器 不属于 MTV 字母,但同样重要:它把 URL 映射给 View。我们通过一个完整的例子来体现:创建一个博客帖子,在视图里查询并打印,然后显示在模板中。
5.1 创建 Post 模型
编辑 hello/models.py:
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
我们定义了一个 Post 表,有标题、正文和自动添加的创建时间。
5.2 生成并执行迁移,观察控制台
迁移是 Django 的“时光机”,能安全地变更数据库结构。首先生成迁移文件:
(django_env) $ python manage.py makemigrations hello
Migrations for 'hello':
hello/migrations/0001_initial.py
- Create model Post
控制台会告诉我们生成了 0001_initial.py,并简述它做了什么。你可以通过 sqlmigrate 查看对应的 SQL 语句(这里展示输出):
(django_env) $ python manage.py sqlmigrate hello 0001
BEGIN;
--
-- Create model Post
--
CREATE TABLE "hello_post" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"title" varchar(100) NOT NULL,
"content" text NOT NULL,
"created_at" datetime NOT NULL
);
COMMIT;
新手注意:sqlmigrate 并不执行迁移,只是打印 SQL,帮助我们验证。实际应用到数据库要执行 migrate:
(django_env) $ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, hello, sessions
Running migrations:
Applying hello.0001_initial... OK
终端清晰地显示了应用的迁移名称和状态 OK。现在数据库里已经有了 hello_post 表。
5.3 用 Django shell 玩转模型 —— 控制台输出的绝佳示例
Django 提供了一个增强版 Python 交互环境,自动加载项目设置和模型:
(django_env) $ python manage.py shell
进入后,我们可以随心所欲地操作模型,所有输出直观可见:
>>> from hello.models import Post
>>> # 创建两条帖子
>>> p1 = Post.objects.create(title="Django 入门", content="MTV 模式很容易理解")
>>> p2 = Post.objects.create(title="Python 之美", content="简洁优雅,强大无比")
>>>
>>> # 查询所有帖子
>>> posts = Post.objects.all()
>>> print(posts)
<QuerySet [<Post: Django 入门>, <Post: Python 之美>]>
>>>
>>> # 过滤查询
>>> p = Post.objects.get(id=1)
>>> print(p.title, p.created_at)
Django 入门 2026-05-13 10:40:22.123456
>>>
>>> # 修改和保存
>>> p.content = "MTV 模式真的很容易理解!"
>>> p.save()
>>>
>>> # 链式查询打印
>>> for post in Post.objects.filter(title__contains='Django'):
... print(f"帖子:{post.title},创建于 {post.created_at}")
...
帖子:Django 入门,创建于 2026-05-13 10:40:22.123456
>>>
>>> exit()
shell 的输出就是最好的老师。你可以在真正写视图之前,先用 shell 验证查询逻辑,观察返回的数据结构,确保思路正确。
5.4 编写视图:查询数据并添加控制台日志
更新 hello/views.py,加入显示帖子列表的视图:
from django.shortcuts import render
from django.http import HttpResponse
from datetime import datetime
from .models import Post
def say_hello(request):
print(f"[{datetime.now()}] say_hello 视图被访问了!")
return HttpResponse("Hello, World! 你好,世界!")
def post_list(request):
# 从数据库取回所有帖子
posts = Post.objects.all().order_by('-created_at')
print(f"[{datetime.now()}] 查询到 {len(posts)} 条帖子") # 控制台日志
# 传递数据给模板渲染
return render(request, 'hello/post_list.html', {'posts': posts})
5.5 创建模板:让数据穿上 HTML 的外衣
在 hello/ 目录下创建 templates/hello/ 两级目录(命名空间约定:应用名/模板名),新建 post_list.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>博客列表</title>
</head>
<body>
<h1>帖子列表</h1>
<a href="/hello/">返回 Hello</a>
<hr>
{% for post in posts %}
<div style="margin-bottom:20px;">
<h2>{{ post.title }}</h2>
<small>{{ post.created_at|date:"Y-m-d H:i" }}</small>
<p>{{ post.content|truncatewords:30 }}</p>
</div>
{% empty %}
<p>还没有帖子。</p>
{% endfor %}
</body>
</html>
这里出现了 Django 模板语法:
-
{% for post in posts %}循环 -
{{ post.title }}变量输出 -
|date和|truncatewords过滤器
5.6 添加 URL 映射
编辑 hello/urls.py,增加新路由:
urlpatterns = [
path('', views.say_hello, name='hello'),
path('posts/', views.post_list, name='post_list'),
]
现在访问 http://127.0.0.1:8000/hello/posts/,你会看到一个帖子列表页面。同时控制台输出:
[2026-05-13 10:45:01] 查询到 2 条帖子
[13/May/2026 10:45:01] "GET /hello/posts/ HTTP/1.1" 200 512
如果我们在 shell 中再多创建几条帖子,页面会动态更新,控制台日志也会随之变化。这就是 MTV 模式的完整协作:
-
浏览器发起 请求
-
URL 配置 匹配到
post_list视图 -
视图 调用 Model (
Post.objects.all()) 从数据库获取数据 -
视图将数据包装为上下文字典
-
视图调用
render()选择 Template 渲染出 HTML -
返回 响应 给浏览器
5.7 进阶调试:在视图中打印请求详情
对于进阶开发者,理解请求对象能帮助我们排错和扩展功能。在 post_list 视图中添加更详细的日志:
def post_list(request):
print("=" * 40)
print(f"请求路径: {request.path}")
print(f"请求方法: {request.method}")
print(f"GET 参数: {request.GET}")
print(f"用户: {request.user}")
print(f"User-Agent: {request.META.get('HTTP_USER_AGENT')}")
posts = Post.objects.all().order_by('-created_at')
print(f"查询到帖子数: {posts.count()}")
print("=" * 40)
return render(request, 'hello/post_list.html', {'posts': posts})
访问页面后,控制台输出:
========================================
请求路径: /hello/posts/
请求方法: GET
GET 参数: <QueryDict: {}>
用户: AnonymousUser
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...
查询到帖子数: 2
========================================
甚至你可以尝试带参数访问:http://127.0.0.1:8000/hello/posts/?debug=true,控制台就会显示 GET 参数: <QueryDict: {'debug': ['true']}>。这对于理解中间件、用户认证和请求流非常有益。
6. MTV 模式 vs MVC 的误解,及 Django 的“智能”调度
很多人刚学 Django 时会听到 “Django 是 MVC 框架”,但官方文档称它为 MTV。其实对应关系很简单:
Django 把“控制器”的部分逻辑分散给了 框架自身的 URL 分发器和视图函数。因此,Django 视图更像一个控制器,而模板才是真正的“视图”。只要记住:视图选择并返回数据,模板渲染数据,这个弯就转过来了。
Django 的请求处理流程(从新手到进阶都应印在脑子里):
浏览器 → Nginx/WSGI → Django 中间件栈 → URL 路由匹配
→ 视图函数(可调用模型) → 加载模板 → 渲染 → HTTP 响应
→ 中间件栈反向处理 → 返回浏览器
开发服务器 runserver 帮我们简化了前面的环节,但中间件、路由、视图这一套逻辑始终一致。
7. 更多控制台输出实例:感知 Django 的生命周期
7.1 观察 SQL 日志
在 settings.py 中,可以添加日志配置,让所有数据库查询打印到控制台:
LOGGING = {
'version': 1,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'level': 'DEBUG',
},
},
}
重启服务器,再次访问帖子列表页,控制台会多出:
(0.001) SELECT "hello_post"."id", "hello_post"."title", ... FROM "hello_post" ORDER BY "hello_post"."created_at" DESC; args=()
这能帮助我们分析 N+1 查询问题,是进阶优化的必备技能。
7.2 利用 manage.py shell_plus(需安装 django-extensions)
进阶用户推荐安装 django-extensions,其提供的 shell_plus 会自动导入所有模型,并支持自动补全:
$ pip install django-extensions
$ # 在 settings.py INSTALLED_APPS 添加 'django_extensions'
$ python manage.py shell_plus
# Shell Plus Model Imports...
from hello.models import Post
...
>>> Post.objects.create(title='快速测试', content='自动导入超方便')
<Post: 快速测试>
输出会列出所有自动导入的模块,让你能立刻开始操作。
8. 结语:从 Hello World 到掌控全局
通过这篇文章,你不仅得到了一个可运行的 Django 环境,更亲手搭建了一个包含控制台日志、数据库查询、模板渲染的 MTV 完整示例。我们从“环境搭建”开始,用 django-admin startproject 和 startapp 命令搭起骨架;利用 runserver 和 print 在终端观察请求动态;深度剖析每个文件职责;最终在 MTV 模式下,用 Model + View + Template 实现了动态帖子列表。
给新手的建议:不要跳过控制台输出。每当迷惑时,就在视图里加一行 print(request.__dict__) 或查看 SQL 日志。Django 的透明性是它的优点,控制台就是你的解剖台。
给进阶者的提醒:你已看到 MTV 的完整链路,可以进一步尝试中间件编程、类视图、基于类的通用视图,甚至深入研究 ASGI 异步视图。但无论技术栈如何变迁,理解请求如何流经项目结构,始终是解决问题的基础。
Django 的第一声 “Hello, World” 只是开始,愿你在接下来的开发中,每一个 print 都能为你照亮前行的路。还可以去公众号、今日头条搜索「IT策士」,一起升级 IT 思维 !