第 12 章 · 毕业项目:shop-demo 电商后台 MVP
本章目标:在 ch01~ch11 基础上,独立交付 shop-demo Django 电商后台最小可行产品(MVP);覆盖商品管理、订单列表、用户登录与 REST API;按 5 天计划实施;通过 100 分验收表自评;完成答辩演示与项目说明文档。
学时建议:5 天 × 6~8 小时(合计 30~40 小时)
前置:完成本模块 ch01~ch11;建议复习 python-dev ch06 OOP 与 ch11 requests;前端联调可参考 frontend-framework ch13 API 章节。
12.1 项目背景与边界
shop-demo 是一家虚构在线书店/杂货铺,面向运营人员提供后台管理能力。C 端商城由独立 SPA 调用 https://api.example.com(或你本地部署的等价 API)——本毕业项目聚焦 Django 后端 + 简易管理界面 + DRF API。
┌──────────────────────────────────────────────────┐
│ shop-demo 后台 MVP(本章) │
├──────────┬──────────┬──────────┬─────────────────┤
│ 用户登录 │ 商品管理 │ 订单列表 │ REST API │
│ Session │ CRUD+封面 │ 分页筛选 │ /api/v1/... │
└──────────┴──────────┴──────────┴─────────────────┘
│
▼
PostgreSQL / SQLite(教学可用)
Redis(缓存,ch10)+ Celery(选修)
| 模块 | MVP 必须 | 不做(加分扩展) |
|---|
| 登录 | 账号密码、退出、未登录拦截 | OAuth、短信验证码 |
| 商品 | 列表、搜索、创建/编辑、封面上传、上下架 | SKU 矩阵、批量导入 |
| 订单 | 列表、状态筛选、详情只读 | 退款、物流对接 |
| API | 商品/订单只读或读写(见验收) | GraphQL、WebSocket |
| 运维 | DEBUG=False 配置说明、Gunicorn 文档 | K8s Helm 全量(见小紫云课) |
严禁将真实公司内部域名、数据库连接串、密钥写入仓库或答辩材料。统一使用 shop-demo、user-demo、api.example.com。
12.2 技术栈清单
| 层级 | 技术 | 对应章节 |
|---|
| 框架 | Django 4.2+ | ch01 |
| API | Django REST Framework | ch07 |
| 认证 | Session + DRF 权限 | ch03、ch07 |
| 模板 | 继承 + {% static %} | ch08 |
| 媒体 | ImageField + MEDIA | ch08 |
| 横切 | 中间件日志、审计字段 | ch09 |
| 性能 | Redis 缓存(商品列表) | ch10 |
| 异步 | Celery 欢迎邮件(选修) | ch10 |
| 测试 | pytest-django | ch11 |
| 部署 | Gunicorn + Nginx + .env | ch11 |
# 推荐项目初始化(若尚未创建)
cd ~/python-learn
django-admin startproject shopdemo shop-demo
cd shop-demo
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install "Django>=4.2,<5" djangorestframework Pillow django-redis celery redis \
pytest pytest-django python-dotenv gunicorn psycopg2-binary
12.3 推荐目录结构
shop-demo/
├── .env.example
├── .github/workflows/test.yml
├── docker-compose.dev.yml # Redis
├── gunicorn.conf.py
├── manage.py
├── pytest.ini
├── requirements.txt
├── docs/
│ ├── API.md
│ └── SELF_REVIEW.md # 100 分自评表
├── shopdemo/
│ ├── settings.py
│ ├── settings_prod.py
│ ├── urls.py
│ ├── wsgi.py
│ └── celery.py
├── core/
│ ├── middleware.py
│ ├── models.py # AuditMixin
│ └── threadlocal.py
├── accounts/ # 登录视图
├── catalog/ # 商品
│ ├── models.py
│ ├── serializers.py
│ ├── views.py
│ ├── web_views.py
│ └── tests/
├── orders/ # 订单
│ ├── models.py
│ ├── serializers.py
│ └── views.py
├── notifications/tasks.py
├── templates/
│ ├── base.html
│ ├── registration/login.html
│ └── catalog/
├── assets/static/...
└── media/ # .gitignore
12.4 数据模型规格
12.4.1 商品 Product
| 字段 | 类型 | 说明 |
|---|
| name | CharField | 商品名 |
| slug | SlugField unique | URL 标识 |
| price | DecimalField | ≥0.01 |
| stock | PositiveIntegerField | 库存 |
| cover | ImageField optional | 封面 |
| description | TextField | 详情 |
| is_published | BooleanField | 是否上架 |
| category | FK Category | 分类 |
| 审计 | AuditMixin | ch09 |
12.4.2 订单 Order
| 字段 | 类型 | 说明 |
|---|
| order_no | CharField unique | 如 SD202603190001 |
| user | FK User | 下单用户(可空,演示用) |
| status | CharField choices | pending/paid/shipped/cancelled |
| total_amount | DecimalField | 订单总额 |
| created_at | DateTimeField | 下单时间 |
12.4.3 订单项 OrderLine(沿用 ch05 命名)
| 字段 | 类型 |
|---|
| order | FK Order |
| product | FK Product |
| quantity | PositiveIntegerField |
| unit_price | DecimalField |
种子数据:python manage.py loaddata demo_products.json demo_orders.json(自备 fixture,≥10 商品、≥20 订单)。
12.5 功能规格
12.5.1 用户登录
| 项 | 规格 |
|---|
| 页面 | /accounts/login/,已登录访问跳转 /dashboard/ |
| 认证 | Django LoginView + Session |
| 保护 | @login_required 装饰管理页;API 写操作 IsAuthenticated |
| 退出 | /accounts/logout/ |
| 演示账号 | operator@user-demo.example.com / 答辩现场说明密码规则 |
12.5.2 商品管理(Web)
| 功能 | 路径 | 要求 |
|---|
| 列表 | /products/ | 分页、按名称搜索 |
| 新建 | /products/new/ | ModelForm + 封面上传 |
| 编辑 | /products/<id>/edit/ | 预填、审计人更新 |
| 上下架 | 表单勾选 is_published | 列表显示状态标签 |
12.5.3 订单列表(Web)
| 功能 | 要求 |
|---|
| 列表 | 分页,默认按时间倒序 |
| 筛选 | ?status=paid |
| 详情 | 只读,展示订单项明细 |
| 权限 | 登录后可看;API 同权 |
12.5.4 REST API
基址:/api/v1/(与 api.example.com/v1 文档对齐为选修)
为何这里是 /api/v1/ 而前文章节是 /api/? ch07~ch15 为教学简洁省略版本段;毕业项目引入 URL 版本化(v1),是企业 API 演进的标准做法。实现时在 shopdemo/urls.py 用 path("api/v1/", include("catalog.api.urls")) 挂载即可,ViewSet 代码不变。
| 方法 | 路径 | 权限 | 说明 |
|---|
| GET | /api/v1/products/ | 公开 | 分页、search、仅上架(可配置) |
| GET | /api/v1/products/{id}/ | 公开 | 详情含 description |
| POST | /api/v1/products/ | 管理员 | 毕业验收可选 |
| GET | /api/v1/orders/ | 登录 | 当前用户或 staff 看全部 |
| GET | /api/v1/orders/{id}/ | 登录 | 含 items |
响应格式遵循 ch07 分页结构;错误含 request_id(ch09)。