Python Flask教程:从Hello World到REST API完整入门指南

📝 931 字 · ☕ 3 分钟阅读

Python Flask教程:从Hello World到REST API完整入门指南

前言:为什么选择Flask

Python Web框架中,Flask以”轻量、灵活、易上手”著称。相比于Django的全家桶式设计,Flask只提供最核心的WSGI工具和路由功能,其余组件(数据库、表单、认证)通过扩展按需集成。这种设计让初学者能快速理解Web应用的运作原理,也让有经验的开发者能灵活定制项目架构。

本教程将从零开始,带你完成:环境搭建 → 第一个Hello World → 路由与模板 → 数据库集成 → REST API开发 → 部署上线,一条完整的Flask学习路径。

环境准备

  • Python 3.8+(推荐 3.10 或 3.11)
  • pip(Python包管理器)
  • 虚拟环境工具(venv)
  • 一个趁手的代码编辑器:VS Code 或 PyCharm

首先创建项目目录并初始化虚拟环境:

# 创建项目目录
mkdir flask-demo
cd flask-demo

# 创建并激活虚拟环境
python3 -m venv venv
source venv/bin/activate  # Linux/Mac
# venv\Scripts\activate  # Windows

# 安装Flask
pip install flask

# 验证安装
python -c "import flask; print(flask.__version__)"

看到输出版本号(如 3.1.x),说明环境已就绪。

第一步:第一个Flask应用(Hello World)

创建 app.py

from flask import Flask

app = Flask(__name__)


@app.route("/")
def hello():
    return "Hello, Flask!"


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

运行:

python app.py

浏览器打开 http://127.0.0.1:5000,你会看到 “Hello, Flask!”。

代码解析:

  • Flask(__name__):创建Flask应用实例,__name__ 帮助框架定位模板和静态文件。
  • @app.route("/"):路由装饰器,将URL路径 / 绑定到下面的函数。
  • debug=True:开发模式,代码修改后自动重启服务器。

第二步:路由与变量规则

Flask的路由系统非常灵活,支持动态URL参数:

from flask import Flask

app = Flask(__name__)


@app.route("/")
def home():
    return "<h1>首页</h1><p>欢迎来到Flask教程</p>"


@app.route("/user/<name>")
def user_profile(name):
    return f"<h1>用户:{name}</h1>"


@app.route("/post/<int:post_id>")
def show_post(post_id):
    return f"<h1>文章 #{post_id}</h1>"


@app.route("/path/<path:subpath>")
def show_subpath(subpath):
    return f"子路径:{subpath}"


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

URL变量转换器:

转换器 说明 示例
string 默认,接受字符串(不含斜杠) /user/<name>
int 接受整数 /post/<int:id>
float 接受浮点数 /price/<float:val>
path 接受斜杠路径 /path/<path:sub>
uuid 接受UUID字符串 /item/<uuid:uid>

第三步:Jinja2模板引擎

Flask内置了强大的Jinja2模板引擎,让你在HTML中嵌入Python表达式。

创建 templates/index.html

<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
    <h1>{{ title }}</h1>
    <p>{{ message }}</p>

    <h2>用户列表</h2>
    <ul>
        {% for user in users %}
        <li>{{ user.name }} - {{ user.email }}</li>
        {% endfor %}
    </ul>
</body>
</html>

创建 app.py

from flask import Flask, render_template

app = Flask(__name__)


@app.route("/")
def index():
    users = [
        {"name": "张三", "email": "zhangsan@example.com"},
        {"name": "李四", "email": "lisi@example.com"},
        {"name": "王五", "email": "wangwu@example.com"},
    ]
    return render_template(
        "index.html",
        title="Flask模板示例",
        message="这是通过Jinja2渲染的页面",
        users=users,
    )


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

Jinja2还支持条件判断、过滤器(如 {{ name|upper }})、模板继承({% extends "base.html" %})等高级功能,是Flask开发中最重要的工具之一。

第四步:数据库集成(SQLAlchemy + Flask-SQLAlchemy)

安装数据库扩展:

pip install flask-sqlalchemy

完整的数据库应用示例:

from flask import Flask, request, jsonify, render_template
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///blog.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)


# 定义模型
class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    content = db.Column(db.Text, nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

    def to_dict(self):
        return {
            "id": self.id,
            "title": self.title,
            "content": self.content,
            "created_at": self.created_at.isoformat(),
        }


# 创建数据库表
with app.app_context():
    db.create_all()


@app.route("/")
def index():
    posts = Post.query.order_by(Post.created_at.desc()).all()
    return render_template("posts.html", posts=posts)


@app.route("/posts", methods=["POST"])
def create_post():
    data = request.get_json()
    post = Post(title=data["title"], content=data["content"])
    db.session.add(post)
    db.session.commit()
    return jsonify(post.to_dict()), 201


@app.route("/posts/<int:post_id>", methods=["GET"])
def get_post(post_id):
    post = db.session.get(Post, post_id)
    if post is None:
        return jsonify({"error": "文章不存在"}), 404
    return jsonify(post.to_dict())


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

关于SQLAlchemy的更多用法,可以参考之前在网站的教程:Python实战:用SQLAlchemy 2.0实现异步数据库操作

第五步:构建REST API

Flask非常适合快速搭建RESTful API。配合之前学的 Python requests库 可以轻松实现前后端分离。

安装 flask-cors 解决跨域问题:

pip install flask-cors

创建一个完整的REST API示例:

from flask import Flask, request, jsonify
from flask_cors import CORS
from datetime import datetime

app = Flask(__name__)
CORS(app)  # 允许跨域请求

# 模拟数据库
tasks = []
next_id = 1


@app.route("/api/tasks", methods=["GET"])
def get_tasks():
    return jsonify(tasks)


@app.route("/api/tasks", methods=["POST"])
def create_task():
    global next_id
    data = request.get_json()
    if not data or "title" not in data:
        return jsonify({"error": "title是必填字段"}), 400

    task = {
        "id": next_id,
        "title": data["title"],
        "done": False,
        "created_at": datetime.now().isoformat(),
    }
    tasks.append(task)
    next_id += 1
    return jsonify(task), 201


@app.route("/api/tasks/<int:task_id>", methods=["GET"])
def get_task(task_id):
    task = next((t for t in tasks if t["id"] == task_id), None)
    if task is None:
        return jsonify({"error": "任务不存在"}), 404
    return jsonify(task)


@app.route("/api/tasks/<int:task_id>", methods=["PUT"])
def update_task(task_id):
    task = next((t for t in tasks if t["id"] == task_id), None)
    if task is None:
        return jsonify({"error": "任务不存在"}), 404

    data = request.get_json()
    task["title"] = data.get("title", task["title"])
    task["done"] = data.get("done", task["done"])
    return jsonify(task)


@app.route("/api/tasks/<int:task_id>", methods=["DELETE"])
def delete_task(task_id):
    global tasks
    task = next((t for t in tasks if t["id"] == task_id), None)
    if task is None:
        return jsonify({"error": "任务不存在"}), 404

    tasks = [t for t in tasks if t["id"] != task_id]
    return jsonify({"message": "已删除"}), 200


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

启动后用 curl 测试:

# 创建任务
curl -X POST http://127.0.0.1:5000/api/tasks \
  -H "Content-Type: application/json" \
  -d '{"title": "学习Flask"}'

# 获取所有任务
curl http://127.0.0.1:5000/api/tasks

# 更新任务
curl -X PUT http://127.0.0.1:5000/api/tasks/1 \
  -H "Content-Type: application/json" \
  -d '{"done": true}'

# 删除任务
curl -X DELETE http://127.0.0.1:5000/api/tasks/1

第六步:部署上线

生产环境推荐使用Gunicorn(Linux)或Waitress(Windows)部署:

pip install gunicorn

# 启动生产服务器(4个worker进程)
gunicorn -w 4 -b 0.0.0.0:8000 app:app

配合之前的 Nginx反向代理配置教程,可以将Flask应用部署到生产环境:

# Nginx配置示例
server {
    listen 80;
    server_name yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

常见问题(FAQ)

Q1: Flask和Django应该学哪个?

初学者建议从Flask入手,它更轻量,能让你理解Web框架的核心概念(路由、请求、响应、模板)。大型项目选Django,微型API或微服务选Flask,两者各有所长。如果你已经学过 FastAPI,你会发现Flask的语法风格非常类似,学习成本很低。

Q2: Flask-SQLAlchemy和直接使用SQLAlchemy有什么区别?

Flask-SQLAlchemy是SQLAlchemy的Flask封装版,自动处理会话管理、应用上下文绑定和配置整合。直接用原生SQLAlchemy也能搭配Flask(如在 SQLAlchemy 2.0教程 中展示的),但需要手动管理会话生命周期。建议Flask项目用Flask-SQLAlchemy,非Flask项目用原生SQLAlchemy。

Q3: Flask应用如何在生产环境处理大量请求?

Flask内置的Werkzeug开发服务器是单线程的,不能用于生产。生产环境使用Gunicorn(多worker + 多线程)或uWSGI,前面再放一层Nginx做反向代理和负载均衡。如果还需要更高并发,可以考虑使用Celery处理后台任务,或者切换到异步框架如FastAPI。

总结

本教程从零开始涵盖了Flask的核心功能:

  • ✅ 环境搭建和第一个应用
  • ✅ 路由规则和URL变量
  • ✅ Jinja2模板引擎
  • ✅ SQLAlchemy数据库集成
  • ✅ REST API构建
  • ✅ 生产部署

下一步可以尝试:结合 Python requests库 调用第三方API实现数据聚合、用 Pandas数据处理 分析返回数据、或者部署到云服务器后用之前学的 Nginx配置 完成HTTPS上线。

📤 分享这篇文章