起因:180分钟的挑战
近日受邀给外经贸大学的学生上两节Python课,每节90分钟。学生有基础,但缺实战经验。
目标很明确:让每个学生在课程结束时,都能拿出一个可以展示的完整项目。
最初想用Django + 爬虫,但很快放弃了:
- Django配置太重,两节课讲不完
- 爬虫不稳定,容易翻车
- 技术栈有点老了
我需要一个更简单、更现代、更可靠的方案。
技术选型:FastAPI + TMDB
为什么是FastAPI?
5行代码就能启动一个API:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
    return {"Hello": "World"}
对比Django需要配置一堆东西,FastAPI的优势太明显:
- ✅ 自动生成API文档(访问 /docs就能测试)
- ✅ 类型提示(现代Python最佳实践)
- ✅ 性能优秀(比Django快很多)
- ✅ 学习曲线平缓
为什么是TMDB?
豆瓣API早就关了,测试第三方接口也都404。TMDB才是正解:
$ curl "https://api.themoviedb.org/3/search/movie?api_key=xxx&query=肖申克&language=zh-CN"
- ✅ 官方免费API
- ✅ 支持中文
- ✅ Netflix在用,够稳定
- ✅ 1分钟申请Key
双模式设计:降低门槛的关键
课堂上最怕什么?学生环境配不好,API申请不下来。
我的解决方案:模拟数据 + 真实API,双模式切换
模式一:开箱即用
# .env
USE_MOCK_DATA=True  # 默认模式
# 内置模拟数据
mock_movies = [
    {"id": 1, "title": "肖申克的救赎", "vote_average": 9.3},
    {"id": 2, "title": "霸王别姬", "vote_average": 9.6}
]
下载代码,直接运行,无需配置。第一节课专注讲概念。
模式二:真实体验
# .env
USE_MOCK_DATA=False
TMDB_API_KEY=你的key
# 自动检测
if USE_MOCK_DATA or not TMDB_API_KEY:
    return mock_data()
else:
    return call_tmdb_api()
课后申请Key,改一行配置,立即切换到真实数据。
课程设计:三步走战略
第一节课:从Hello到API(90分钟)
Step 1: Hello FastAPI (20分钟)
@app.get("/hello/{name}")
def greet(name: str):
    return {"message": f"Hello, {name}!"}
学会:路由、参数、返回值
Step 2: 电影API (20分钟)
@app.get("/movies")
def get_movies(genre: str = None):
    return filter_movies(genre)
学会:RESTful设计、查询参数
Step 3: TMDB集成 (30分钟)
@app.get("/search")
async def search(q: str):
    return await call_tmdb(q)
学会:异步编程、API调用、环境变量
第二节课:完整应用(90分钟)
- 前端界面 (25分钟):Jinja2、响应式布局
- 功能完善 (30分钟):AJAX、收藏、统计
- 部署准备 (20分钟):配置管理、GitHub
实战中的三个坑
1. 页面闪烁
// ❌ 问题
document.getElementById('list').innerHTML = '加载中...';
// ✅ 解决:加状态锁
let isLoading = false;
if (isLoading) return;
isLoading = true;
2. 中文URL编码
# ❌ 错误
curl 'http://localhost:8000/search?q=阿甘正传'
# ✅ 正确
curl --data-urlencode "q=阿甘正传" -G 'http://localhost:8000/search'
3. 虚拟环境失效
重命名项目后虚拟环境失效?因为内部保存了绝对路径。
rm -rf venv
python3 -m venv venv
source venv/bin/activate
配置管理:API Key别泄露
# ❌ 危险
TMDB_API_KEY = "444d85..."  
# ✅ 正确
# .env
TMDB_API_KEY=你的key
# config.py
from dotenv import load_dotenv
load_dotenv()
API_KEY = os.getenv("TMDB_API_KEY", "")
.env
*.pyc
__pycache__/
venv/
教学设计的五个原则
1. 降低门槛,提高天花板
- 模拟数据让所有人都能跑起来
- 真实API让高手有进阶空间
2. 渐进式学习
- Step 1: Hello World(建立信心)
- Step 2: 基础API(理解概念)
- Step 3: 真实集成(接触实战)
- Lesson 2: 完整应用(综合运用)
3. 预设问题
学生肯定会遇到的问题,提前在文档里写好答案:
- 虚拟环境配置
- API Key申请
- 中文参数编码
- 端口占用
4. 真实但不复杂
- ✅ 用真实技术栈(FastAPI、TMDB)
- ❌ 不引入数据库、认证、复杂异步
- ✅ 聚焦核心概念
5. 提供扩展方向
### 进阶挑战
1. 添加用户登录
2. 数据库持久化
3. 部署到云服务器
4. 实现推荐算法
技术对比
FastAPI vs Flask vs Django
| 特性 | FastAPI | Flask | Django | 
|---|---|---|---|
| 学习曲线 | ⭐⭐ | ⭐ | ⭐⭐⭐⭐ | 
| 自动文档 | ✅ | ❌ | ❌ | 
| 适合教学 | ✅ | △ | ❌ | 
结论:两节课教学,FastAPI最优。
TMDB vs 豆瓣
| API | 状态 | 推荐度 | 
|---|---|---|
| TMDB | 稳定免费 | ⭐⭐⭐⭐⭐ | 
| 豆瓣 | 已关闭 | ⭐ | 
结论:TMDB是唯一选择。
文档的力量
我准备了完整的文档体系:
- README.md:项目总览
- STUDENT_GUIDE.md:详细教程(含API申请步骤)
- teaching_guide.md:90分钟时间表
- exercises.md:练习题
甚至提供了TMDB申请表的英文模板,学生直接复制粘贴就行。
好的文档就是好的设计。如果你无法用简单语言解释一个设计,说明设计有问题。
测试清单
虽然是教学项目,但我还是测试了所有功能:
# Lesson 1
✅ Hello World
✅ 路径参数
✅ 查询参数  
✅ RESTful API
✅ 模拟数据模式
✅ 真实API模式
# Lesson 2
✅ 搜索功能
✅ 热门榜单
✅ 收藏系统
✅ 统计分析
✅ 响应式布局
发现并修复了:模拟数据格式错误、404问题、URL编码、页面闪烁等bug。
写在最后
从想法到实现,这个项目经历了:
- 📊 3次技术栈调整
- 🔧 5次重大重构
- 📝 完整的文档
- ✅ 全面的测试
- ⏰ 20+小时准备
但这是值得的。180分钟内,学生能:
- ✨ 体会编程乐趣
- 💡 理解Web核心概念
- 🚀 接触真实开发流程
- 🎯 获得可展示的项目
更重要的是,展示了工程师的思考方式:
- 理解约束(时间、水平)
- 技术选型(FastAPI + TMDB)
- 设计方案(双模式、渐进式)
- 工程实践(配置、文档、测试)
项目已开源:https://github.com/Polly2014/tmdb_movie_sourse
欢迎Star、Fork,更欢迎提Issue分享你的想法!
