环境搭建与第一个“Hello, World”:Django 项目结构与 MTV 模式详解

0 阅读4分钟

作者: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,请始终使用 python3pip3 命令。

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

进阶点:这里的 print 输出与 Django 的请求日志出现在同一终端。在生产环境中(如使用 Gunicorn),print 会输出到服务器日志流,是快速调试的利器。但请记得调试完删除 print,正式环境请使用标准 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 的命令执行器。我们常用的 runserverstartappmigrateshell 都是由此进入。

你运行的 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.pyasgi.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:应用配置,可在 settingsINSTALLED_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 模式的完整协作:

  1. 浏览器发起 请求

  2. URL 配置 匹配到 post_list 视图

  3. 视图 调用 Model (Post.objects.all()) 从数据库获取数据

  4. 视图将数据包装为上下文字典

  5. 视图调用 render() 选择 Template 渲染出 HTML

  6. 返回 响应 给浏览器

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 startprojectstartapp 命令搭起骨架;利用 runserverprint 在终端观察请求动态;深度剖析每个文件职责;最终在 MTV 模式下,用 Model + View + Template 实现了动态帖子列表。

给新手的建议:不要跳过控制台输出。每当迷惑时,就在视图里加一行 print(request.__dict__) 或查看 SQL 日志。Django 的透明性是它的优点,控制台就是你的解剖台。

给进阶者的提醒:你已看到 MTV 的完整链路,可以进一步尝试中间件编程、类视图、基于类的通用视图,甚至深入研究 ASGI 异步视图。但无论技术栈如何变迁,理解请求如何流经项目结构,始终是解决问题的基础。

Django 的第一声 “Hello, World” 只是开始,愿你在接下来的开发中,每一个 print 都能为你照亮前行的路。还可以去公众号、今日头条搜索「IT策士」,一起升级 IT 思维 !