第 1 章 · Django 项目结构与 MTV 实战
本章目标:理解 Django MTV(Model–Template–View)架构与请求生命周期;使用 django-admin startproject shopdemo 创建电商后台练习项目;按业务拆分多个 App(catalog、accounts);掌握 settings 分环境的基本概念;完成从 blogdemo 迁移到 shop-demo 的目录规划;能独立运行开发服务器并解释每个核心文件的作用。
学时建议:4~5 小时(含 1.5 小时跟练)
前置:完成 python-dev 模块 ch10(venv/pip)与 ch15(Django 快速入门 / blogdemo);会使用终端与文件管理器。
1.1 场景说明:从博客到电商后台
你在 python-dev ch15 中用 blogdemo 完成了「文章列表 + 详情 + Admin」。现在要接手一个虚构练习项目 shop-demo(电商商品后台),需要:
| 需求 | blogdemo 现状 | shop-demo 目标 |
|---|---|---|
| 数据实体 | Post 文章 | Product 商品、Category 分类 |
| 用户体系 | 仅 Admin 超管 | 运营账号 + 权限分组(ch03 详讲) |
| 对外 API | 无 | 预留 api.example.com 联调(ch07 DRF) |
| 项目命名 | blogdemo | shopdemo(Django 项目包名) |
说明:本章所有路径、域名、密钥均为教学虚构,不涉及任何真实公司仓库、内部配置或生产域名。
学习路径(django-web)
ch01 项目结构 → ch02 表单 → ch03 认证 → ch04 CBV
↑ 你在这里
1.2 MTV 与请求生命周期
1.2.1 MTV 对照表
| 层次 | 文件位置 | 职责 | shop-demo 示例 |
|---|---|---|---|
| Model | models.py | 数据结构、ORM、校验规则 | Product、Category |
| Template | templates/ | HTML 渲染、表单展示 | catalog/product_list.html |
| View | views.py | 接收请求、调用 Model、选模板 | product_list(request) |
Django 的 View 相当于经典 MVC 中的 Controller;Template 对应 View(表现层)。
1.2.2 一次 HTTP 请求的完整路径
浏览器 GET /catalog/
│
▼
① WSGI/ASGI 入口 (wsgi.py / asgi.py)
│
▼
② 中间件链 (settings.MIDDLEWARE) — 安全头、Session 等
│
▼
③ URL 路由 (shopdemo/urls.py → catalog/urls.py)
│
▼
④ 视图函数/类 (catalog/views.py)
│ ├─ 查询 ORM:Product.objects.filter(...)
│ └─ 组装 context 字典
▼
⑤ 模板引擎渲染 (DjangoTemplates)
│
▼
⑥ HttpResponse 返回 HTML
| 阶段 | 可打断点位置 | 常见调试命令 |
|---|---|---|
| 路由 | urls.py | python manage.py show_urls(需 django-extensions) |
| 视图 | views.py | print(request.method) |
| ORM | models.py / shell | Product.objects.all().query |
| 模板 | .html | 模板中加 {{ debug }}(DEBUG=True 时) |
1.3 创建 shopdemo 项目
1.3.1 环境准备
cd ~/python-learn
python -m venv .venv
# Windows
.venv\Scripts\activate
# macOS / Linux
# source .venv/bin/activate
pip install "Django>=4.2,<5"
django-admin --version
1.3.2 初始化项目
django-admin startproject shopdemo
cd shopdemo
python manage.py runserver
浏览器访问 http://127.0.0.1:8000/,看到火箭欢迎页即成功。
1.3.3 推荐目录结构(多 App)
shopdemo/ # 仓库根(练习用 shop-demo)
├── manage.py
├── requirements.txt # pip freeze 输出
├── .env.example # 环境变量示例(不含真实密钥)
├── config/ # 可选:settings 分包(见 1.5)
│ ├── __init__.py
│ ├── settings/
│ │ ├── base.py
│ │ ├── dev.py
│ │ └── prod.py
│ ├── urls.py
│ ├── wsgi.py
│ └── asgi.py
├── catalog/ # 商品目录 App
│ ├── models.py
│ ├── views.py
│ ├── urls.py
│ ├── admin.py
│ └── templates/catalog/
├── accounts/ # 账号 App
│ ├── models.py
│ └── views.py
└── templates/ # 全局模板(可选)
└── base.html
官方startproject默认生成shopdemo/shopdemo/嵌套包,教学中可保持默认,也可重命名为config/。关键是 App 按业务拆分,而非全部堆在一个models.py里。
1.4 创建并注册多个 App
python manage.py startapp catalog
python manage.py startapp accounts
shopdemo/settings.py(或 config/settings/base.py)中注册:
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
# 本地 App
"catalog.apps.CatalogConfig",
"accounts.apps.AccountsConfig",
]
| App | 职责 | 为何独立 |
|---|---|---|
catalog | 商品、分类、库存字段 | 核心业务,后续 ch02~ch06 主战场 |
accounts | 登录页、个人资料扩展 | 与商品解耦,便于权限测试 |
django.contrib.* | 认证、Session、Admin | 框架内置,勿删 |
1.5 settings 分环境概念
开发、测试、生产的环境变量不同,不要把生产密钥写进代码。
1.5.1 单文件 vs 分包
| 方式 | 适用 | 说明 |
|---|---|---|
单文件 settings.py | 入门、小练习 | ch01~ch03 足够 |
分包 settings/base.py + dev.py + prod.py | 团队协作 | 本模块推荐逐步过渡 |
1.5.2 分包示例
config/settings/base.py(公共片段):
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent.parent
SECRET_KEY = "django-insecure-teaching-only" # 教学占位
INSTALLED_APPS = ["django.contrib.admin", "django.contrib.auth",
"django.contrib.contenttypes", "django.contrib.sessions",
"django.contrib.messages", "django.contrib.staticfiles",
"catalog", "accounts"]
ROOT_URLCONF = "config.urls"
DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3"}}
LANGUAGE_CODE = "zh-hans"
TIME_ZONE = "Asia/Shanghai"