Python-web开发之Flask框架入门

Python Web 开发之 Flask 框架入门

一、Flask 简介

Flask 是一个基于 Python 的轻量级 Web 框架,由 Armin Ronacher 开发。它的设计哲学是微框架(Micro Framework)------核心保持简洁,功能通过扩展实现。

核心特点:

  • 轻量:核心代码精简,不绑定数据库、表单验证等组件
  • 灵活:可自由选择 ORM、模板引擎等组件
  • 易学:API 直观,上手快
  • Jinja2 模板:内置强大的模板引擎
  • Werkzeug WSGI:基于成熟的 WSGI 工具库
  • 扩展丰富:社区提供大量高质量扩展

安装:

bash 复制代码
pip install flask

二、第一个 Flask 应用

python 复制代码
from flask import Flask

app = Flask(__name__)

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

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

运行:

bash 复制代码
python app.py

访问 http://127.0.0.1:5000 即可看到页面。

app.run() 常用参数:

参数 说明 默认值
host 监听地址 127.0.0.1
port 监听端口 5000
debug 开启调试模式(热重载 + 详细错误页) False

三、路由

3.1 基本路由

python 复制代码
@app.route("/about")
def about():
    return "About Page"

@app.route("/contact")
def contact():
    return "Contact Page"

3.2 变量规则

python 复制代码
@app.route("/user/<username>")
def show_user(username):
    return f"User: {username}"

# 指定类型
@app.route("/post/<int:post_id>")
def show_post(post_id):
    return f"Post ID: {post_id}"

@app.route("/price/<float:price>")
def show_price(price):
    return f"Price: {price}"

# 路径类型
@app.route("/file/<path:filename>")
def show_file(filename):
    return f"File: {filename}"

支持的类型转换器:

转换器 说明
string 默认,接受不含 / 的字符串
int 整数
float 浮点数
path / 的字符串
uuid UUID 字符串

3.3 HTTP 方法

python 复制代码
from flask import request

@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "GET":
        return "Login Page"
    elif request.method == "POST":
        username = request.form.get("username")
        password = request.form.get("password")
        return f"Login: {username}"

3.4 构造 URL

python 复制代码
from flask import url_for

@app.route("/user/<username>")
def profile(username):
    return f"Profile: {username}"

# 在视图函数或模板中使用
url_for("profile", username="alice")
# 输出: /user/alice

url_for 的优势:自动处理特殊字符和转义,修改路由规则时无需到处改 URL。

四、请求与响应

4.1 Request 对象

python 复制代码
from flask import request

@app.route("/search")
def search():
    # URL 参数: /search?q=flask&page=1
    keyword = request.args.get("q")
    page = request.args.get("page", 1, type=int)

    # 请求头
    user_agent = request.headers.get("User-Agent")

    # 客户端 IP
    ip = request.remote_addr

    # 请求方法
    method = request.method

    return f"Search: {keyword}, Page: {page}"

4.2 处理表单与 JSON

python 复制代码
@app.route("/api/data", methods=["POST"])
def handle_data():
    # 表单数据 (application/x-www-form-urlencoded / multipart)
    name = request.form.get("name")

    # JSON 数据 (application/json)
    json_data = request.get_json()
    title = json_data.get("title")

    # 原始请求体
    raw_data = request.data

    return {"status": "ok", "name": name}

4.3 Response 对象

python 复制代码
from flask import jsonify, make_response

@app.route("/api/info")
def info():
    # 返回 JSON
    return jsonify({"version": "1.0", "name": "myapp"})

@app.route("/download")
def download():
    # 自定义响应
    response = make_response("Hello World")
    response.headers["Content-Type"] = "text/plain"
    response.headers["X-Custom"] = "value"
    response.set_cookie("session_id", "abc123")
    return response

@app.route("/redirect-demo")
def redirect_demo():
    from flask import redirect
    return redirect("/about")

五、模板引擎(Jinja2)

5.1 渲染模板

项目结构:

复制代码
myapp/
├── app.py
└── templates/
    ├── base.html
    ├── index.html
    └── user.html
python 复制代码
from flask import render_template

@app.route("/")
def index():
    return render_template("index.html", title="首页", items=["Apple", "Banana"])

5.2 模板语法

html 复制代码
<!-- base.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    {% block content %}{% endblock %}
</body>
</html>
html 复制代码
<!-- index.html -->
{% extends "base.html" %}

{% block title %}{{ title }}{% endblock %}

{% block content %}
    <h1>{{ title }}</h1>
    <ul>
    {% for item in items %}
        <li>{{ item }}</li>
    {% endfor %}
    </ul>
{% endblock %}

5.3 常用模板功能

html 复制代码
<!-- 条件判断 -->
{% if user %}
    <p>欢迎, {{ user.name }}</p>
{% else %}
    <p>请登录</p>
{% endif %}

<!-- 循环 -->
{% for post in posts %}
    <h2>{{ post.title }}</h2>
{% else %}
    <p>暂无文章</p>
{% endfor %}

<!-- 过滤器 -->
<p>{{ content | truncate(100) }}</p>
<p>{{ date | datetimeformat("%Y-%m-%d") }}</p>
<p>{{ name | upper }}</p>
<p>{{ content | safe }}</p>  {# 不转义 HTML #}

<!-- 自定义过滤器 -->
{{ price | round(2) }}

5.4 自定义过滤器

python 复制代码
@app.template_filter("reverse")
def reverse_filter(s):
    return s[::-1]

# 模板中使用: {{ "hello" | reverse }}  输出 olleh

六、会话管理

python 复制代码
from flask import make_response, request

@app.route("/set-cookie")
def set_cookie():
    resp = make_response("Cookie set")
    resp.set_cookie("username", "alice", max_age=3600, httponly=True)
    return resp

@app.route("/get-cookie")
def get_cookie():
    username = request.cookies.get("username")
    return f"Username: {username}"

6.2 Session

python 复制代码
from flask import session

app.secret_key = "your-secret-key-here"  # 生产环境务必使用安全密钥

@app.route("/login", methods=["POST"])
def login():
    session["user_id"] = 42
    session["username"] = "alice"
    return "Login success"

@app.route("/profile")
def profile():
    user_id = session.get("user_id")
    if not user_id:
        return "Please login", 401
    return f"User ID: {user_id}"

@app.route("/logout")
def logout():
    session.clear()
    return "Logged out"

七、蓝图(Blueprint)------模块化开发

蓝图用于将应用拆分为多个模块,适合中大型项目。

7.1 项目结构

复制代码
myapp/
├── app.py
├── auth/
│   ├── __init__.py
│   └── routes.py
├── blog/
│   ├── __init__.py
│   └── routes.py
└── templates/

7.2 定义蓝图

python 复制代码
# auth/routes.py
from flask import Blueprint

auth_bp = Blueprint("auth", __name__, url_prefix="/auth")

@auth_bp.route("/login")
def login():
    return "Login Page"

@auth_bp.route("/register")
def register():
    return "Register Page"
python 复制代码
# blog/routes.py
from flask import Blueprint

blog_bp = Blueprint("blog", __name__, url_prefix="/blog")

@blog_bp.route("/")
def index():
    return "Blog Index"

@blog_bp.route("/<int:post_id>")
def show_post(post_id):
    return f"Post: {post_id}"

7.3 注册蓝图

python 复制代码
# app.py
from flask import Flask
from auth.routes import auth_bp
from blog.routes import blog_bp

app = Flask(__name__)
app.secret_key = "your-secret-key"

app.register_blueprint(auth_bp)
app.register_blueprint(blog_bp)

八、数据库集成(Flask-SQLAlchemy)

8.1 安装与配置

bash 复制代码
pip install flask-sqlalchemy
python 复制代码
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

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

db = SQLAlchemy(app)

8.2 定义模型

python 复制代码
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    posts = db.relationship("Post", backref="author", lazy=True)

    def __repr__(self):
        return f"<User {self.username}>"

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(200), nullable=False)
    content = db.Column(db.Text, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)

8.3 增删改查

python 复制代码
# 创建表
with app.app_context():
    db.create_all()

# 新增
user = User(username="alice", email="alice@example.com")
db.session.add(user)
db.session.commit()

# 查询
user = User.query.filter_by(username="alice").first()
users = User.query.all()
user = User.query.get(1)

# 修改
user.email = "new@example.com"
db.session.commit()

# 删除
db.session.delete(user)
db.session.commit()

九、表单处理(Flask-WTF)

bash 复制代码
pip install flask-wtf
python 复制代码
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Email, Length

app.config["SECRET_KEY"] = "your-secret-key"

class LoginForm(FlaskForm):
    username = StringField("Username", validators=[DataRequired(), Length(min=3, max=20)])
    email = StringField("Email", validators=[DataRequired(), Email()])
    password = PasswordField("Password", validators=[DataRequired(), Length(min=6)])
    submit = SubmitField("Login")

视图函数:

python 复制代码
@app.route("/login", methods=["GET", "POST"])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        # 处理登录逻辑
        return f"Welcome, {form.username.data}"
    return render_template("login.html", form=form)

模板:

html 复制代码
<form method="POST">
    {{ form.hidden_tag() }}
    <div>
        {{ form.username.label }}
        {{ form.username() }}
        {% for error in form.username.errors %}
            <span style="color:red">{{ error }}</span>
        {% endfor %}
    </div>
    <div>
        {{ form.password.label }}
        {{ form.password() }}
    </div>
    <div>{{ form.submit() }}</div>
</form>

十、错误处理

python 复制代码
@app.errorhandler(404)
def not_found(error):
    return render_template("404.html"), 404

@app.errorhandler(500)
def server_error(error):
    return render_template("500.html"), 500

自定义异常:

python 复制代码
class NotFoundError(Exception):
    pass

@app.errorhandler(NotFoundError)
def handle_not_found(error):
    return jsonify({"error": str(error)}), 404

十一、中间件与钩子

Flask 提供了请求生命周期中的钩子函数:

python 复制代码
@app.before_request
def before_request():
    """每个请求前执行"""
    print(f"Request: {request.path}")

@app.after_request
def after_request(response):
    """每个请求后执行,可以修改响应"""
    response.headers["X-Request-ID"] = "abc123"
    return response

@app.teardown_request
def teardown_request(exception):
    """请求结束后执行(无论是否异常)"""
    print("Request finished")

@app.context_processor
def inject_globals():
    """向所有模板注入变量"""
    return {"site_name": "MyApp"}

十二、RESTful API 开发

12.1 返回 JSON

python 复制代码
@app.route("/api/users", methods=["GET"])
def get_users():
    users = User.query.all()
    return jsonify([{"id": u.id, "name": u.username} for u in users])

@app.route("/api/users", methods=["POST"])
def create_user():
    data = request.get_json()
    if not data or "username" not in data:
        return jsonify({"error": "Username is required"}), 400
    user = User(username=data["username"])
    db.session.add(user)
    db.session.commit()
    return jsonify({"id": user.id, "username": user.username}), 201

@app.route("/api/users/<int:user_id>", methods=["PUT"])
def update_user(user_id):
    user = User.query.get_or_404(user_id)
    data = request.get_json()
    user.username = data.get("username", user.username)
    db.session.commit()
    return jsonify({"id": user.id, "username": user.username})

@app.route("/api/users/<int:user_id>", methods=["DELETE"])
def delete_user(user_id):
    user = User.query.get_or_404(user_id)
    db.session.delete(user)
    db.session.commit()
    return "", 204

12.2 使用 Flask-RESTful

bash 复制代码
pip install flask-restful
python 复制代码
from flask_restful import Resource, Api

api = Api(app)

class UserResource(Resource):
    def get(self, user_id):
        user = User.query.get_or_404(user_id)
        return {"id": user.id, "username": user.username}

    def delete(self, user_id):
        user = User.query.get_or_404(user_id)
        db.session.delete(user)
        db.session.commit()
        return "", 204

api.add_resource(UserResource, "/api/users/<int:user_id>")

十三、部署

13.1 生产环境 WSGI 服务器

Flask 内置服务器不适合生产环境,推荐使用 Gunicorn:

bash 复制代码
pip install gunicorn
gunicorn -w 4 -b 0.0.0.0:8000 "app:app"

参数说明:

  • -w 4:4 个 worker 进程
  • -b 0.0.0.0:8000:监听地址和端口

13.2 配置管理

python 复制代码
# config.py
class Config:
    DEBUG = False
    SECRET_KEY = "prod-secret-key"
    SQLALCHEMY_DATABASE_URI = "postgresql://user:pass@localhost/db"

class DevelopmentConfig(Config):
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = "sqlite:///dev.db"

class TestingConfig(Config):
    TESTING = True
    SQLALCHEMY_DATABASE_URI = "sqlite:///test.db"
python 复制代码
# app.py
app.config.from_object("config.DevelopmentConfig")
# 或从环境变量
app.config.from_envvar("APP_SETTINGS")

十四、常用扩展一览

扩展 用途
Flask-SQLAlchemy ORM 数据库操作
Flask-Migrate 数据库迁移(Alembic)
Flask-WTF 表单验证
Flask-Login 用户认证
Flask-RESTful RESTful API
Flask-JWT-Extended JWT 认证
Flask-CORS 跨域支持
Flask-Caching 缓存
Flask-Mail 邮件发送
Flask-DebugToolbar 调试工具栏
Flask-Limiter 接口限流
Flask-Admin 后台管理界面

十五、总结

Flask 的核心优势在于简洁与灵活

  • 小项目:单文件即可快速搭建
  • 中项目:通过蓝图实现模块化
  • 大项目:配合扩展可以覆盖认证、ORM、API、缓存等全套需求

学习路径建议:

复制代码
路由与视图 → 模板渲染 → 请求与响应 → 表单处理
    → 数据库集成 → 蓝图模块化 → 认证授权 → RESTful API → 部署
相关推荐
河马老师2 小时前
写这需求快崩溃了,幸好我会装饰器模式
前端·javascript·面试
用户5757303346242 小时前
🚀 拒绝“CSS 命名困难症”!手把手带你用 Tailwind CSS 搓一个“高颜值”登录页
前端
文静小土豆2 小时前
标签和选择器(Label和 Selector)
linux·前端
Birdy_x2 小时前
接口自动化项目实战(8):请求封装
python·自动化·测试用例
wuhen_n2 小时前
《Vue3+TS+Vite 高效编程与优化实践》专栏收尾
前端·javascript·vue.js
kevinten102 小时前
折腾三个月,我把摩旅路线和 AI 搞在一起了
前端
偷光2 小时前
大模型核心技术概述:Token、Prompt、Tool与Agent的关系详解
前端·ai·prompt·ai编程
鹏程十八少2 小时前
8. Android 深入插件化Shadow源码:揭秘插件Activity启动的完整链路(源码解析)
java·前端·面试
wuhen_n2 小时前
Function Calling解剖:从请求到响应的完整数据流
前端·人工智能·ai编程