第 1 课:Flask 简介与环境配置(Markdown 教案)
📘 课程目标
- 了解 Flask 框架及特点
- 完成开发环境配置
- 创建并运行第一个 Flask 应用
- 掌握基本路由和请求处理
- 理解Flask项目结构和最佳实践
🧠 一、什么是 Flask?
Flask 是一个基于 Python 的轻量级 Web 框架,适合快速构建 Web 应用和 API。
🔹 Flask 的特点:
- 轻量灵活:核心功能简洁,可扩展性强
- 开发友好:内置开发服务器与调试器
- 模板系统:内置路由系统与模板引擎 Jinja2
- 丰富生态:插件丰富(如 Flask-Login、Flask-Migrate、Flask-SQLAlchemy)
- RESTful 支持:天然支持 RESTful API 开发
🆚 Flask vs Django:
特点 | Flask | Django |
---|---|---|
学习曲线 | 平缓 | 陡峭 |
灵活性 | 高 | 中等 |
内置功能 | 少(需插件) | 多(开箱即用) |
适用场景 | 小到中型项目、API | 大型复杂项目 |
⚙️ 二、环境配置
✅ 安装步骤:
- 创建项目目录:
mkdir flask_project
cd flask_project
- 创建虚拟环境(推荐):
# 创建虚拟环境
python -m venv venv# 激活虚拟环境
source venv/bin/activate # Mac/Linux
venv\Scripts\activate.bat # Windows(CMD)
venv\Scripts\Activate.ps1 # Windows(PowerShell)
- 安装 Flask:
pip install flask
- 验证安装:
python -m flask --version
🛠️ 推荐的开发工具:
- 代码编辑器:VS Code、PyCharm
- 版本控制:Git
- API 测试:Postman、curl
- 数据库管理:SQLite Browser
🚀 三、第一个 Flask 应用(Hello Flask)
📁 项目结构(推荐):
flask_project/
├── venv/ # 虚拟环境
├── app.py # 主应用文件
├── requirements.txt # 依赖列表
└── README.md # 项目说明
💻 基础应用代码:
# app.pyfrom flask import Flask# 创建 Flask 应用实例
app = Flask(__name__)# 基础路由
@app.route('/')
def index():return "<h1>Hello, Flask!</h1>"# 带参数的路由
@app.route('/user/<name>')
def user(name):return f"<h1>Hello, {name}!</h1>"# 指定HTTP方法
@app.route('/about', methods=['GET'])
def about():return "<h1>这是关于页面</h1>"if __name__ == '__main__':app.run(debug=True, host='127.0.0.1', port=5000)
✅ 运行命令:
python app.py
默认运行在 http://127.0.0.1:5000
📌 四、Flask 应用详解
🔧 核心组件说明:
Flask(__name__)
:创建应用实例,__name__
帮助Flask定位资源@app.route('/')
:装饰器定义URL路由规则debug=True
:开启调试模式,代码修改自动重载host
和port
:指定服务器地址和端口
🛣️ 路由详解:
# 1. 基础路由
@app.route('/')
def index():return "首页"# 2. 动态路由
@app.route('/user/<username>')
def show_user(username):return f"用户:{username}"# 3. 类型转换
@app.route('/post/<int:post_id>')
def show_post(post_id):return f"文章ID:{post_id}"# 4. 多种HTTP方法
@app.route('/login', methods=['GET', 'POST'])
def login():return "登录页面"
📱 支持的转换器类型:
string
:默认类型,接受任何不包含斜杠的文本int
:接受正整数float
:接受正浮点数path
:类似string,但接受斜杠uuid
:接受UUID字符串
🌟 五、进阶功能示例
📄 HTML 模板:
from flask import Flask, render_templateapp = Flask(__name__)@app.route('/hello/<name>')
def hello(name):return render_template('hello.html', name=name)
创建 templates/hello.html
:
<!DOCTYPE html>
<html>
<head><title>Hello {{ name }}</title>
</head>
<body><h1>Hello, {{ name }}!</h1>
</body>
</html>
📊 JSON API:
from flask import Flask, jsonifyapp = Flask(__name__)@app.route('/api/users')
def get_users():users = [{'id': 1, 'name': 'Alice'},{'id': 2, 'name': 'Bob'}]return jsonify(users)
🎯 错误处理:
@app.errorhandler(404)
def not_found(error):return '<h1>页面未找到</h1>', 404@app.errorhandler(500)
def internal_error(error):return '<h1>服务器内部错误</h1>', 500
🧪 六、实践练习
🎯 练习 1:基础路由
- 修改返回内容为
"你好,Flask!"
- 添加一个新的
/about
路由,返回"这是关于页面"
- 尝试使用不同端口运行应用:
app.run(port=8080)
🎯 练习 2:动态路由
创建以下路由:
/user/<name>
:显示用户信息/product/<int:id>
:显示产品详情(id必须为整数)/category/<path:category_path>
:显示分类路径
🎯 练习 3:简单API
创建一个简单的任务管理API:
GET /tasks
:返回所有任务的JSONGET /tasks/<int:task_id>
:返回特定任务的JSON
💡 七、最佳实践与小贴士
✅ 开发建议:
- 始终使用虚拟环境:避免包冲突
- 开启调试模式:方便开发调试
- 使用环境变量:存储敏感配置
- 遵循PEP 8:代码风格规范
- 及时处理错误:提供友好的错误页面
🔒 安全注意事项:
# 生产环境中关闭调试模式
if __name__ == '__main__':app.run(debug=False)# 使用环境变量存储密钥
import os
app.secret_key = os.environ.get('SECRET_KEY', 'dev-key')
📦 依赖管理:
# 生成依赖文件
pip freeze > requirements.txt# 安装依赖
pip install -r requirements.txt
🐛 八、常见问题解答
❓ Q1:ModuleNotFoundError: No module named ‘flask’
A: 确保已激活虚拟环境并安装了Flask:
source venv/bin/activate
pip install flask
❓ Q2:Address already in use 错误
A: 端口被占用,更换端口或停止占用该端口的进程:
app.run(port=8080) # 更换端口
❓ Q3:模板未找到错误
A: 确保在项目根目录创建了 templates
文件夹,并将HTML文件放入其中。
❓ Q4:静态文件(CSS/JS)无法加载
A: 将静态文件放在 static
文件夹中,并使用 url_for
引用:
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
✅ 完整示例代码
# app.py
from flask import Flask, render_template, jsonifyapp = Flask(__name__)# 基础路由
@app.route('/')
def index():return "<h1>欢迎来到 Flask 学习!</h1>"# 动态路由
@app.route('/user/<name>')
def user(name):return f"<h1>Hello, {name}!</h1>"# 关于页面
@app.route('/about')
def about():return "<h1>这是关于页面</h1>"# API示例
@app.route('/api/info')
def api_info():return jsonify({'name': 'Flask学习应用','version': '1.0','author': '学员'})# 错误处理
@app.errorhandler(404)
def not_found(error):return '<h1>404 - 页面未找到</h1>', 404if __name__ == '__main__':app.run(debug=True, host='127.0.0.1', port=5000)
📚 下节课预告
下节课我们将学习:
- Flask 模板系统(Jinja2)
- 表单处理与验证
- 静态文件管理
- 会话管理
🎓 课后作业
- 完成所有练习题
- 创建一个个人简介页面,包含姓名、专业、兴趣爱好
- 实现一个简单的计算器API(加、减、乘、除)
- 阅读Flask官方文档的快速入门部分
提交要求:将代码上传到个人GitHub仓库,并发送链接。
📝 练习题答案
🎯 练习 1 答案:基础路由
# practice1.py
from flask import Flaskapp = Flask(__name__)# 1. 修改返回内容为中文
@app.route('/')
def index():return "<h1>欢迎来到 Flask 学习! </h1>"# 2. 添加关于页面路由
@app.route('/about')
def about():return "这是关于页面"if __name__ == '__main__':# 3. 使用不同端口运行app.run(debug=True, port=8080)
🎯 练习 2 答案:动态路由
# practice2.py
from flask import Flaskapp = Flask(__name__)# 显示用户信息
@app.route('/user/<name>')
def show_user(name):return f"""<h1>用户信息</h1><p>用户名:{name}</p><p>欢迎访问我们的网站!</p>"""# 显示产品详情(id必须为整数)
@app.route('/product/<int:id>')
def show_product(id):return f"""<h1>产品详情</h1><p>产品ID:{id}</p><p>产品类型:数字产品</p>"""# 显示分类路径
@app.route('/category/<path:category_path>')
def show_category(category_path):return f"""<h1>产品分类</h1><p>分类路径:{category_path}</p><p>您正在浏览:{category_path.replace('/', ' > ')}</p>"""if __name__ == '__main__':app.run(debug=True)
🎯 练习 3 答案:简单API
# practice3.py
from flask import Flask, jsonifyapp = Flask(__name__)# 模拟任务数据
tasks = [{"id": 1, "title": "学习Flask基础", "completed": False, "priority": "high"},{"id": 2, "title": "完成练习题", "completed": False, "priority": "medium"},{"id": 3, "title": "准备下节课", "completed": True, "priority": "low"}
]# 获取所有任务
@app.route('/tasks')
def get_all_tasks():return jsonify({"success": True,"count": len(tasks),"tasks": tasks})# 获取特定任务
@app.route('/tasks/<int:task_id>')
def get_task(task_id):# 查找任务task = next((t for t in tasks if t["id"] == task_id), None)if task:return jsonify({"success": True,"task": task})else:return jsonify({"success": False,"message": f"任务 {task_id} 未找到"}), 404if __name__ == '__main__':app.run(debug=True)
🎓 课后作业答案
📝 作业 1:个人简介页面
# assignment1.py
from flask import Flask, render_templateapp = Flask(__name__)@app.route('/')
def index():return '''<h1>欢迎访问我的个人网站</h1><nav><a href="/profile">个人简介</a> |<a href="/skills">技能专长</a> |<a href="/contact">联系方式</a></nav>'''@app.route('/profile')
def profile():return '''<h1>个人简介</h1><div style="font-family: Arial; line-height: 1.6; max-width: 600px;"><h2>基本信息</h2><p><strong>姓名:</strong>张三</p><p><strong>专业:</strong>计算机科学与技术</p><p><strong>年级:</strong>大三</p><h2>兴趣爱好</h2><ul><li>🖥️ 编程开发</li><li>📚 阅读技术书籍</li><li>🎮 游戏开发</li><li>🏃♂️ 跑步健身</li></ul><h2>学习目标</h2><p>希望通过学习Flask框架,能够开发出实用的Web应用,为将来的职业发展打下坚实基础。</p><a href="/">返回首页</a></div>'''@app.route('/skills')
def skills():return '''<h1>技能专长</h1><div style="font-family: Arial; line-height: 1.6;"><h2>编程语言</h2><ul><li>Python ⭐⭐⭐⭐</li><li>JavaScript ⭐⭐⭐</li><li>Java ⭐⭐⭐</li><li>HTML/CSS ⭐⭐⭐⭐</li></ul><h2>框架技术</h2><ul><li>Flask (学习中)</li><li>Vue.js</li><li>Bootstrap</li></ul><a href="/">返回首页</a></div>'''@app.route('/contact')
def contact():return '''<h1>联系方式</h1><div style="font-family: Arial; line-height: 1.6;"><p>📧 邮箱:zhangsan@example.com</p><p>📱 电话:138-0000-0000</p><p>🔗 GitHub:github.com/zhangsan</p><p>🏫 学校:XX大学计算机学院</p><a href="/">返回首页</a></div>'''if __name__ == '__main__':app.run(debug=True)
🧮 作业 2:计算器API
# assignment2.py
from flask import Flask, jsonify, requestapp = Flask(__name__)@app.route('/')
def index():return '''<h1>Flask 计算器 API</h1><h2>API 使用说明</h2><div style="font-family: monospace; background: #f5f5f5; padding: 20px;"><p><strong>加法:</strong> GET /add?a=10&b=5</p><p><strong>减法:</strong> GET /subtract?a=10&b=5</p><p><strong>乘法:</strong> GET /multiply?a=10&b=5</p><p><strong>除法:</strong> GET /divide?a=10&b=5</p><p><strong>综合计算:</strong> POST /calculate</p></div><h2>在线测试</h2><p><a href="/add?a=10&b=5">测试加法: 10 + 5</a></p><p><a href="/subtract?a=10&b=3">测试减法: 10 - 3</a></p><p><a href="/multiply?a=6&b=7">测试乘法: 6 × 7</a></p><p><a href="/divide?a=20&b=4">测试除法: 20 ÷ 4</a></p>'''# 加法
@app.route('/add')
def add():try:a = float(request.args.get('a', 0))b = float(request.args.get('b', 0))result = a + breturn jsonify({"operation": "addition","operands": {"a": a, "b": b},"result": result,"expression": f"{a} + {b} = {result}"})except ValueError:return jsonify({"error": "请提供有效的数字参数"}), 400# 减法
@app.route('/subtract')
def subtract():try:a = float(request.args.get('a', 0))b = float(request.args.get('b', 0))result = a - breturn jsonify({"operation": "subtraction","operands": {"a": a, "b": b},"result": result,"expression": f"{a} - {b} = {result}"})except ValueError:return jsonify({"error": "请提供有效的数字参数"}), 400# 乘法
@app.route('/multiply')
def multiply():try:a = float(request.args.get('a', 0))b = float(request.args.get('b', 0))result = a * breturn jsonify({"operation": "multiplication","operands": {"a": a, "b": b},"result": result,"expression": f"{a} × {b} = {result}"})except ValueError:return jsonify({"error": "请提供有效的数字参数"}), 400# 除法
@app.route('/divide')
def divide():try:a = float(request.args.get('a', 0))b = float(request.args.get('b', 0))if b == 0:return jsonify({"error": "除数不能为零"}), 400result = a / breturn jsonify({"operation": "division","operands": {"a": a, "b": b},"result": result,"expression": f"{a} ÷ {b} = {result}"})except ValueError:return jsonify({"error": "请提供有效的数字参数"}), 400# 综合计算(支持POST请求)
@app.route('/calculate', methods=['POST'])
def calculate():try:data = request.get_json()if not data:return jsonify({"error": "请提供JSON格式的数据"}), 400a = float(data.get('a', 0))b = float(data.get('b', 0))operation = data.get('operation', '').lower()if operation == 'add':result = a + bsymbol = '+'elif operation == 'subtract':result = a - bsymbol = '-'elif operation == 'multiply':result = a * bsymbol = '×'elif operation == 'divide':if b == 0:return jsonify({"error": "除数不能为零"}), 400result = a / bsymbol = '÷'else:return jsonify({"error": "不支持的运算类型,支持:add, subtract, multiply, divide"}), 400return jsonify({"operation": operation,"operands": {"a": a, "b": b},"result": result,"expression": f"{a} {symbol} {b} = {result}","timestamp": str(app.datetime.now()) if hasattr(app, 'datetime') else "N/A"})except (ValueError, TypeError):return jsonify({"error": "请提供有效的数字参数"}), 400except Exception as e:return jsonify({"error": f"计算错误:{str(e)}"}), 500# 获取所有支持的操作
@app.route('/operations')
def get_operations():return jsonify({"supported_operations": [{"name": "add", "description": "加法运算", "example": "/add?a=10&b=5"},{"name": "subtract", "description": "减法运算", "example": "/subtract?a=10&b=5"},{"name": "multiply", "description": "乘法运算", "example": "/multiply?a=10&b=5"},{"name": "divide", "description": "除法运算", "example": "/divide?a=10&b=5"}],"post_endpoint": {"url": "/calculate","method": "POST","format": {"a": "number","b": "number", "operation": "string (add/subtract/multiply/divide)"}}})if __name__ == '__main__':import datetimeapp.datetime = datetimeapp.run(debug=True)
📋 作业 3:完整的项目结构示例
flask_homework/
├── venv/ # 虚拟环境
├── app.py # 主应用文件
├── requirements.txt # 依赖文件
├── README.md # 项目说明
├── templates/ # 模板文件夹
│ ├── base.html
│ ├── index.html
│ └── profile.html
└── static/ # 静态文件夹├── css/│ └── style.css└── js/└── main.js
requirements.txt 内容:
Flask==2.3.3
Werkzeug==2.3.7
README.md 内容:
# Flask 学习项目这是Flask课程第一课的作业项目。## 功能特性- 个人简介展示
- 计算器API
- 动态路由示例
- JSON API响应## 安装运行1. 创建虚拟环境:```bashpython -m venv venvsource venv/bin/activate # Mac/Linux
-
安装依赖:
pip install -r requirements.txt
-
运行应用:
python app.py
-
访问 http://127.0.0.1:5000
API 文档
详见代码注释和 /operations
端点。
---## 💡 学习小贴士### 🔍 调试技巧:1. **使用调试模式**:`debug=True` 可以自动重载代码
2. **查看控制台输出**:运行时的错误信息很有帮助
3. **使用浏览器开发者工具**:检查网络请求和响应
4. **添加print语句**:在函数中添加打印语句来跟踪执行流程### 🚀 进阶建议:1. **学习使用Postman测试API**
2. **尝试添加错误处理和参数验证**
3. **探索Flask的官方文档和示例**
4. **练习编写单元测试**### 📖 推荐阅读:- [Flask官方文档](https://flask.palletsprojects.com/)
- [Flask快速入门教程](https://flask.palletsprojects.com/quickstart/)
- [Python Web开发最佳实践](https://docs.python-guide.org/scenarios/web/)---