第 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 大型复杂项目

⚙️ 二、环境配置

✅ 安装步骤:
  1. 创建项目目录
bash 复制代码
mkdir flask_project
cd flask_project
  1. 创建虚拟环境(推荐):
bash 复制代码
# 创建虚拟环境
python -m venv venv

# 激活虚拟环境
source venv/bin/activate    # Mac/Linux
venv\Scripts\activate.bat   # Windows(CMD)
venv\Scripts\Activate.ps1   # Windows(PowerShell)
  1. 安装 Flask
bash 复制代码
pip install flask
  1. 验证安装
bash 复制代码
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          # 项目说明
💻 基础应用代码:
python 复制代码
# app.py

from 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)
✅ 运行命令:
bash 复制代码
python app.py

默认运行在 http://127.0.0.1:5000


📌 四、Flask 应用详解

🔧 核心组件说明:
  • Flask(__name__) :创建应用实例,__name__ 帮助Flask定位资源
  • @app.route('/'):装饰器定义URL路由规则
  • debug=True:开启调试模式,代码修改自动重载
  • hostport:指定服务器地址和端口
🛣️ 路由详解:
python 复制代码
# 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 模板:
python 复制代码
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/hello/<name>')
def hello(name):
    return render_template('hello.html', name=name)

创建 templates/hello.html

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>Hello {{ name }}</title>
</head>
<body>
    <h1>Hello, {{ name }}!</h1>
</body>
</html>
📊 JSON API:
python 复制代码
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/api/users')
def get_users():
    users = [
        {'id': 1, 'name': 'Alice'},
        {'id': 2, 'name': 'Bob'}
    ]
    return jsonify(users)
🎯 错误处理:
python 复制代码
@app.errorhandler(404)
def not_found(error):
    return '<h1>页面未找到</h1>', 404

@app.errorhandler(500)
def internal_error(error):
    return '<h1>服务器内部错误</h1>', 500

🧪 六、实践练习

🎯 练习 1:基础路由
  1. 修改返回内容为 "你好,Flask!"
  2. 添加一个新的 /about 路由,返回 "这是关于页面"
  3. 尝试使用不同端口运行应用:app.run(port=8080)
🎯 练习 2:动态路由

创建以下路由:

  • /user/<name>:显示用户信息
  • /product/<int:id>:显示产品详情(id必须为整数)
  • /category/<path:category_path>:显示分类路径
🎯 练习 3:简单API

创建一个简单的任务管理API:

  • GET /tasks:返回所有任务的JSON
  • GET /tasks/<int:task_id>:返回特定任务的JSON

💡 七、最佳实践与小贴士

✅ 开发建议:
  1. 始终使用虚拟环境:避免包冲突
  2. 开启调试模式:方便开发调试
  3. 使用环境变量:存储敏感配置
  4. 遵循PEP 8:代码风格规范
  5. 及时处理错误:提供友好的错误页面
🔒 安全注意事项:
python 复制代码
# 生产环境中关闭调试模式
if __name__ == '__main__':
    app.run(debug=False)

# 使用环境变量存储密钥
import os
app.secret_key = os.environ.get('SECRET_KEY', 'dev-key')
📦 依赖管理:
bash 复制代码
# 生成依赖文件
pip freeze > requirements.txt

# 安装依赖
pip install -r requirements.txt

🐛 八、常见问题解答

❓ Q1:ModuleNotFoundError: No module named 'flask'

A: 确保已激活虚拟环境并安装了Flask:

bash 复制代码
source venv/bin/activate
pip install flask
❓ Q2:Address already in use 错误

A: 端口被占用,更换端口或停止占用该端口的进程:

python 复制代码
app.run(port=8080)  # 更换端口
❓ Q3:模板未找到错误

A: 确保在项目根目录创建了 templates 文件夹,并将HTML文件放入其中。

❓ Q4:静态文件(CSS/JS)无法加载

A: 将静态文件放在 static 文件夹中,并使用 url_for 引用:

html 复制代码
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">

✅ 完整示例代码

python 复制代码
# app.py
from flask import Flask, render_template, jsonify

app = 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>', 404

if __name__ == '__main__':
    app.run(debug=True, host='127.0.0.1', port=5000)

📚 下节课预告

下节课我们将学习:

  • Flask 模板系统(Jinja2)
  • 表单处理与验证
  • 静态文件管理
  • 会话管理

🎓 课后作业

  1. 完成所有练习题
  2. 创建一个个人简介页面,包含姓名、专业、兴趣爱好
  3. 实现一个简单的计算器API(加、减、乘、除)
  4. 阅读Flask官方文档的快速入门部分

提交要求:将代码上传到个人GitHub仓库,并发送链接。


📝 练习题答案

🎯 练习 1 答案:基础路由

python 复制代码
# practice1.py
from flask import Flask

app = 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 答案:动态路由

python 复制代码
# practice2.py
from flask import Flask

app = 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

python 复制代码
# practice3.py
from flask import Flask, jsonify

app = 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} 未找到"
        }), 404

if __name__ == '__main__':
    app.run(debug=True)

🎓 课后作业答案

📝 作业 1:个人简介页面

python 复制代码
# assignment1.py
from flask import Flask, render_template

app = 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

python 复制代码
# assignment2.py
from flask import Flask, jsonify, request

app = 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 + b
        
        return 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 - b
        
        return 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 * b
        
        return 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": "除数不能为零"}), 400
            
        result = a / b
        
        return 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格式的数据"}), 400
            
        a = float(data.get('a', 0))
        b = float(data.get('b', 0))
        operation = data.get('operation', '').lower()
        
        if operation == 'add':
            result = a + b
            symbol = '+'
        elif operation == 'subtract':
            result = a - b
            symbol = '-'
        elif operation == 'multiply':
            result = a * b
            symbol = '×'
        elif operation == 'divide':
            if b == 0:
                return jsonify({"error": "除数不能为零"}), 400
            result = a / b
            symbol = '÷'
        else:
            return jsonify({"error": "不支持的运算类型,支持:add, subtract, multiply, divide"}), 400
            
        return 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": "请提供有效的数字参数"}), 400
    except 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 datetime
    app.datetime = datetime
    app.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 内容:

markdown 复制代码
# Flask 学习项目

这是Flask课程第一课的作业项目。

## 功能特性

- 个人简介展示
- 计算器API
- 动态路由示例
- JSON API响应

## 安装运行

1. 创建虚拟环境:
   ```bash
   python -m venv venv
   source venv/bin/activate  # Mac/Linux
  1. 安装依赖:

    bash 复制代码
    pip install -r requirements.txt
  2. 运行应用:

    bash 复制代码
    python app.py
  3. 访问 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/)

---
相关推荐
IT_102430 分钟前
Spring Boot项目开发实战销售管理系统——系统设计!
大数据·spring boot·后端
ai小鬼头1 小时前
AIStarter最新版怎么卸载AI项目?一键删除操作指南(附路径设置技巧)
前端·后端·github
Touper.2 小时前
SpringBoot -- 自动配置原理
java·spring boot·后端
思则变2 小时前
[Pytest] [Part 2]增加 log功能
开发语言·python·pytest
一只叫煤球的猫2 小时前
普通程序员,从开发到管理岗,为什么我越升职越痛苦?
前端·后端·全栈
一只鹿鹿鹿2 小时前
信息化项目验收,软件工程评审和检查表单
大数据·人工智能·后端·智慧城市·软件工程
漫谈网络3 小时前
WebSocket 在前后端的完整使用流程
javascript·python·websocket
专注VB编程开发20年3 小时前
开机自动后台运行,在Windows服务中托管ASP.NET Core
windows·后端·asp.net
程序员岳焱3 小时前
Java 与 MySQL 性能优化:MySQL全文检索查询优化实践
后端·mysql·性能优化
一只叫煤球的猫3 小时前
手撕@Transactional!别再问事务为什么失效了!Spring-tx源码全面解析!
后端·spring·面试