Flask是Python最流行的轻量级Web框架,核心简洁、扩展灵活。不管是快速写个API服务还是搭建小型Web应用,Flask都是很好的选择。这篇文章从安装到RESTful API,快速过一遍Flask的核心功能。
安装
pip install flask
最小应用
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "Hello, Flask!"
if __name__ == "__main__":
app.run(debug=True)
$ python app.py
* Running on http://127.0.0.1:5000
debug=True开启调试模式,代码修改后自动重载,报错时显示详细信息(生产环境一定要关掉)。
路由
# 基本路由
@app.route("/about")
def about():
return "About page"
# 动态路由
@app.route("/user/<username>")
def user_profile(username):
return f"User: {username}"
# 指定类型
@app.route("/post/<int:post_id>")
def show_post(post_id):
return f"Post #{post_id}"
# 支持的转换器:string(默认), int, float, path, uuid
# 指定HTTP方法
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
return do_login()
return show_login_form()
请求处理
from flask import request
@app.route("/search")
def search():
# 查询参数: /search?q=python&page=1
keyword = request.args.get("q", "")
page = request.args.get("page", 1, type=int)
return f"Search: {keyword}, page: {page}"
@app.route("/submit", methods=["POST"])
def submit():
# 表单数据
name = request.form.get("name")
email = request.form.get("email")
return f"Received: {name}, {email}"
@app.route("/upload", methods=["POST"])
def upload():
# 文件上传
file = request.files.get("file")
if file:
file.save(f"./uploads/{file.filename}")
return "Upload OK"
return "No file", 400
JSON响应
写API时最常用的就是JSON响应:
from flask import jsonify, request
@app.route("/api/users", methods=["GET"])
def list_users():
users = [
{"id": 1, "name": "Alice", "email": "alice@example.com"},
{"id": 2, "name": "Bob", "email": "bob@example.com"},
]
return jsonify({"code": 0, "data": users})
@app.route("/api/users", methods=["POST"])
def create_user():
data = request.get_json()
if not data or "name" not in data:
return jsonify({"code": 400, "msg": "name is required"}), 400
# 这里实际项目中会写入数据库
new_user = {
"id": 3,
"name": data["name"],
"email": data.get("email", "")
}
return jsonify({"code": 0, "data": new_user}), 201
模板渲染
Flask内置Jinja2模板引擎。在templates/目录下放HTML文件:
templates/index.html:
<!DOCTYPE html>
<html>
<head><title>{{ title }}</title></head>
<body>
<h1>{{ title }}</h1>
<ul>
{% for item in items %}
<li>{{ item.name }} - {{ item.price }}元</li>
{% endfor %}
</ul>
</body>
</html>
from flask import render_template
@app.route("/products")
def products():
items = [
{"name": "键盘", "price": 299},
{"name": "鼠标", "price": 99},
]
return render_template("index.html", title="商品列表", items=items)
错误处理
from flask import abort
@app.route("/api/users/<int:uid>")
def get_user(uid):
user = find_user_by_id(uid)
if user is None:
abort(404)
return jsonify(user)
# 自定义错误处理
@app.errorhandler(404)
def not_found(error):
return jsonify({"code": 404, "msg": "Not Found"}), 404
@app.errorhandler(500)
def server_error(error):
return jsonify({"code": 500, "msg": "Internal Server Error"}), 500
Blueprint模块化
项目大了之后用Blueprint拆分模块:
# api/user.py
from flask import Blueprint, jsonify
user_bp = Blueprint("user", __name__, url_prefix="/api/user")
@user_bp.route("/list")
def user_list():
return jsonify({"users": []})
@user_bp.route("/<int:uid>")
def user_detail(uid):
return jsonify({"id": uid, "name": "Alice"})
# app.py
from flask import Flask
from api.user import user_bp
app = Flask(__name__)
app.register_blueprint(user_bp)
完整的API示例
把上面的知识点串起来,做一个简单的待办事项API:
from flask import Flask, jsonify, request, abort
app = Flask(__name__)
todos = []
next_id = 1
@app.route("/api/todos", methods=["GET"])
def list_todos():
return jsonify({"code": 0, "data": todos})
@app.route("/api/todos", methods=["POST"])
def add_todo():
global next_id
data = request.get_json()
if not data or "title" not in data:
return jsonify({"code": 400, "msg": "title required"}), 400
todo = {
"id": next_id,
"title": data["title"],
"done": False
}
next_id += 1
todos.append(todo)
return jsonify({"code": 0, "data": todo}), 201
@app.route("/api/todos/<int:tid>", methods=["PUT"])
def update_todo(tid):
data = request.get_json()
for todo in todos:
if todo["id"] == tid:
todo["done"] = data.get("done", todo["done"])
todo["title"] = data.get("title", todo["title"])
return jsonify({"code": 0, "data": todo})
abort(404)
@app.route("/api/todos/<int:tid>", methods=["DELETE"])
def delete_todo(tid):
global todos
todos = [t for t in todos if t["id"] != tid]
return jsonify({"code": 0, "msg": "deleted"})
if __name__ == "__main__":
app.run(debug=True, port=5000)
小结
Flask的设计哲学是微框架——核心只提供路由和请求处理,其他功能通过扩展实现。入门容易、灵活度高,适合API服务和中小型Web应用。如果项目复杂度上来了,可以考虑加上Flask-SQLAlchemy、Flask-Migrate、Flask-JWT等扩展,或者直接换Django。