Python---Flask 轻量级Web框架

1. Flask 基础认知

Flask是由Armin Ronacher开发的轻量级Python Web框架,基于Werkzeug(WSGI工具集)和Jinja2(模板引擎)构建,被称为"微框架(Microframework)"------并非功能薄弱,而是核心极简,可通过扩展灵活扩展功能,对比Django(大而全的框架),Flask更适合小型项目、快速原型开发或需要高度定制化的场景。

核心特点

  • 轻量灵活:核心仅包含路由、请求/响应处理、模板渲染,其余功能通过扩展实现;
  • 易学易用:API设计简洁,新手可快速上手;
  • 兼容性好:支持Python 3.6+,兼容主流WSGI服务器;
  • 丰富的扩展生态:Flask-SQLAlchemy(数据库)、Flask-WTF(表单)、Flask-Login(用户认证)等。

环境搭建

首先推荐使用虚拟环境隔离依赖(避免全局环境污染):

bash 复制代码
# 创建虚拟环境(Python 3.6+)
python -m venv flask_env

# 激活虚拟环境(Windows)
flask_env\Scripts\activate
# 激活虚拟环境(Linux/Mac)
source flask_env/bin/activate

# 安装Flask
pip install flask
# 验证安装
python -c "import flask; print(flask.__version__)"
2. 最小应用:Flask 核心骨架

Flask的最小应用仅需几行代码即可运行,是理解其核心流程的起点:

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

# 初始化Flask应用:__name__表示当前模块名,Flask以此定位静态文件/模板路径
app = Flask(__name__)

# 路由:将URL路径(/)与视图函数绑定
@app.route('/')
def index():
    # 视图函数:处理请求并返回响应
    return 'Hello, Flask!'

# 仅在直接运行该脚本时启动开发服务器
if __name__ == '__main__':
    # debug=True:开启调试模式(代码修改自动重启、报错显示详细信息)
    app.run(debug=True, host='0.0.0.0', port=5000)

运行脚本后,访问http://localhost:5000即可看到"Hello, Flask!",核心要素:

  • Flask(__name__):创建应用实例,__name__是Flask的"应用根目录"标识;
  • @app.route('/'):路由装饰器,映射URL与视图函数;
  • app.run():启动开发服务器(仅用于开发环境,生产环境需用Gunicorn/Nginx)。
3. 路由系统:URL与视图的映射

视图函数(View Function)是 Flask 中绑定到特定 URL 路由的 Python 函数,也是处理 HTTP 请求的核心载体

路由是Flask的核心之一,负责将用户请求的URL匹配到对应的视图函数,支持多种高级特性:

(1)基本路由与动态路由
python 复制代码
# 基本路由:固定URL
@app.route('/about')
def about():
    return '关于我们'

# 动态路由:URL参数(<string:name> 表示接收字符串类型的name参数)
@app.route('/user/<string:name>')  # 类型可省略,默认string;支持int/float/path(含/的字符串)
def user(name):
    return f'Hello, {name}!'

# 多URL绑定到同一个视图函数
@app.route('/hi')
@app.route('/hello')
def greet():
    return 'Hi there!'
(2)请求方法限定

默认路由仅支持GET请求,可通过methods参数指定支持的HTTP方法(GET/POST/PUT/DELETE等):

python 复制代码
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        # 处理POST请求(表单提交)
        return '处理登录逻辑'
    else:
        # 处理GET请求(返回登录页面)
        return '返回登录表单'
(3)路由规则进阶
  • strict_slashes:控制URL末尾的/是否严格匹配(默认True,/about/与/about视为不同);
  • redirect_to:路由重定向;
python 复制代码
@app.route('/old-path', strict_slashes=False, redirect_to='/new-path')
def old_path():
    pass

@app.route('/new-path')
def new_path():
    return '新路径'
4. 请求与响应处理

Flask通过request对象封装客户端请求数据,通过返回值/make_response构建响应。

(1)请求对象(request)

需先导入from flask import request,核心属性:

属性/方法 说明 示例
request.method 请求方法(GET/POST等) if request.method == 'POST'
request.args GET参数(URL中的?参数) request.args.get('page', 1)
request.form POST表单数据 request.form.get('username')
request.files 上传的文件 request.files['avatar']
request.cookies 请求中的Cookie request.cookies.get('token')
request.headers 请求头信息 request.headers.get('User-Agent')

访问http://localhost:5000/user?id=100\&page=2 → 返回 "获取到的 GET 参数:用户 ID=100,页码 = 2"。

URL 中的?是路径和 GET 参数的分隔符,& 是多个 GET 参数之间的分隔符

示例:处理GET/POST请求

python 复制代码
from flask import Flask, request

app = Flask(__name__)

@app.route('/data', methods=['GET', 'POST'])
def handle_data():
    if request.method == 'GET':
        # 获取GET参数:?name=张三&age=20
        name = request.args.get('name', '匿名')  # 第二个参数是默认值
        age = request.args.get('age', 0, type=int)
        return f'GET请求:姓名{name},年龄{age}'
    else:
        # 获取POST表单数据
        username = request.form['username']  # 无默认值,不存在则抛异常
        password = request.form.get('password')
        return f'POST请求:用户名{username}'

if __name__ == '__main__':
    app.run(debug=True)
(2)响应处理

Flask支持多种响应类型,核心方式:

  • 直接返回字符串:自动封装为Response对象(默认状态码200,Content-Type: text/html);
  • 返回元组:(响应内容, 状态码, 响应头);
  • 使用make_response构建自定义响应;
  • 返回JSON:使用jsonify(自动设置Content-Type: application/json)。

示例:

python 复制代码
from flask import Flask, make_response, jsonify

app = Flask(__name__)

@app.route('/response1')
def response1():
    # 返回元组:内容、状态码、响应头
    return '自定义状态码', 404, {'X-Custom-Header': 'Flask'}

@app.route('/response2')
def response2():
    # 手动构建Response对象
    resp = make_response('自定义响应')
    resp.status_code = 201
    resp.set_cookie('token', '123456')  # 设置Cookie
    resp.headers['Content-Type'] = 'text/plain'
    return resp

@app.route('/json')
def return_json():
    # 返回JSON数据(推荐用jsonify,而非json.dumps)
    data = {'name': '张三', 'age': 20}
    return jsonify(data)  # 等价于 return make_response(json.dumps(data), 200, {'Content-Type': 'application/json'})

if __name__ == '__main__':
    app.run(debug=True)
(3)重定向与错误处理
  • 重定向:使用redirect,配合url_for(反向生成URL,避免硬编码);
  • 错误处理:使用@app.errorhandler(状态码)装饰器自定义错误页面。
python 复制代码
from flask import Flask, redirect, url_for, abort

app = Flask(__name__)

@app.route('/index')
def index():
    return '首页'

@app.route('/go-index')
def go_index():
    # url_for('index'):根据视图函数名生成URL(/index)
    return redirect(url_for('index'))

@app.route('/error')
def error():
    # 主动抛出404异常
    abort(404)

# 自定义404错误页面
@app.errorhandler(404)
def page_not_found(e):
    # e是异常对象,包含错误信息
    return '页面不存在', 404

# 自定义500错误页面
@app.errorhandler(500)
def server_error(e):
    return '服务器内部错误', 500

if __name__ == '__main__':
    app.run(debug=True)
5. 模板引擎:Jinja2

Flask内置Jinja2模板引擎,用于将Python变量渲染到HTML中,实现"前后端分离(简易版)",模板文件默认放在项目根目录的templates文件夹下。

(1)基本使用

项目结构:

复制代码
project/
├── app.py
└── templates/
    └── index.html

app.py

python 复制代码
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    # 渲染模板:传递变量name/age到模板
    return render_template('index.html', name='张三', age=20)

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

templates/index.html:

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>Flask模板</title>
</head>
<body>
    <h1>Hello, {{ name }}!</h1>  {# 变量渲染 #}
    <p>年龄:{{ age + 1 }}</p>    {# 支持简单表达式 #}
</body>
</html>
(2)Jinja2核心语法
  • 变量:{``{ 变量名 }},支持字典({``{ user.name }}/{``{ user['name'] }})、列表({``{ list[0] }});
  • 控制结构:{% if/for %},需闭合{% endif/endfor %}
html 复制代码
{# 条件判断 #}
{% if age >= 18 %}
    <p>成年</p>
{% else %}
    <p>未成年</p>
{% endif %}

{# 循环 #}
<ul>
{% for item in ['苹果', '香蕉', '橙子'] %}
    <li>{{ loop.index }}: {{ item }}</li>  {# loop.index是循环索引(从1开始) #}
{% endfor %}
</ul>
  • 模板继承:通过{% extends %}/{% block %}实现模板复用(核心减少重复代码);
    基模板(templates/base.html):

    html 复制代码
    <!DOCTYPE html>
    <html>
    <head>
        <title>{% block title %}默认标题{% endblock %}</title>
    </head>
    <body>
        <div class="header">头部</div>
        <div class="content">
            {% block content %}{% endblock %}  {# 子模板填充的内容 #}
        </div>
        <div class="footer">底部</div>
    </body>
    </html>

    子模板(templates/home.html):

    html 复制代码
    {% extends 'base.html' %}  {# 继承基模板 #}
    
    {% block title %}首页{% endblock %}  {# 重写title块 #}
    
    {% block content %}
        <h1>首页内容</h1>
    {% endblock %}
  • 宏(Macro):类似函数,封装可复用的HTML片段;

html 复制代码
{% macro input(name, type='text', value='') %}
    <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}

{# 使用宏 #}
{{ input('username') }}
{{ input('password', type='password') }}
  • 过滤器:修改变量显示格式,{``{ 变量|过滤器 }},常用:safe(禁用转义)、length(长度)、upper(大写);
html 复制代码
{{ '<h1>测试</h1>'|safe }}  {# 渲染为<h1>测试</h1>,而非转义后的字符串 #}
{{ ['a','b']|length }}       {# 输出2 #}
{{ 'hello'|upper }}          {# 输出HELLO #}
6. 会话与状态管理

HTTP是无状态协议,Flask通过Cookie和Session实现状态保持:

(1)Cookie

Cookie是存储在客户端浏览器的小型文本文件,Flask通过set_cookie/request.cookies操作:

python 复制代码
from flask import Flask, make_response, request

app = Flask(__name__)

@app.route('/set-cookie')
def set_cookie():
    resp = make_response('设置Cookie')
    # 设置Cookie:key=value,max_age是过期时间(秒)
    resp.set_cookie('username', '张三', max_age=3600)
    return resp

@app.route('/get-cookie')
def get_cookie():
    # 获取Cookie
    username = request.cookies.get('username', '匿名')
    return f'Cookie中的用户名:{username}'

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

Session是"服务器端的Cookie":将敏感数据存储在服务器,仅将加密的session_id存储在客户端Cookie中,使用前需设置密钥(SECRET_KEY)用于加密:

python 复制代码
from flask import Flask, session

app = Flask(__name__)
# 必须设置密钥(开发时可随便写,生产环境需用随机强密钥)
app.secret_key = 'your-secret-key-123456'  # 生产环境建议从环境变量读取

@app.route('/set-session')
def set_session():
    # 存储数据到Session
    session['username'] = '张三'
    session['age'] = 20
    return 'Session已设置'

@app.route('/get-session')
def get_session():
    # 获取Session数据
    username = session.get('username', '匿名')
    age = session.get('age', 0)
    return f'Session:用户名{username},年龄{age}'

@app.route('/clear-session')
def clear_session():
    # 删除单个Session键
    session.pop('age', None)
    # 清空所有Session
    # session.clear()
    return 'Session已清理'

if __name__ == '__main__':
    app.run(debug=True)
7. 蓝图(Blueprint):模块化开发

当项目规模扩大时,单一app.py会变得臃肿,蓝图(Blueprint)可将功能拆分为独立模块(如用户模块、商品模块),实现代码解耦。

示例:拆分用户模块和商品模块

项目结构:

复制代码
project/
├── app.py
├── users/
│   ├── __init__.py
│   └── views.py  # 用户模块视图
└── goods/
    ├── __init__.py
    └── views.py  # 商品模块视图

users/views.py:

python 复制代码
from flask import Blueprint

# 创建蓝图:第一个参数是蓝图名,第二个是模块名,url_prefix是该蓝图所有路由的前缀
user_bp = Blueprint('user', __name__, url_prefix='/user')

# 蓝图的路由(最终URL:/user/login)
@user_bp.route('/login')
def login():
    return '用户登录'

@user_bp.route('/profile')
def profile():
    return '用户个人中心'

goods/views.py:

python 复制代码
from flask import Blueprint

goods_bp = Blueprint('goods', __name__, url_prefix='/goods')

@goods_bp.route('/list')
def goods_list():
    return '商品列表'

@goods_bp.route('/detail/<int:id>')
def goods_detail(id):
    return f'商品详情:{id}'

app.py(注册蓝图):

python 复制代码
from flask import Flask
from users.views import user_bp
from goods.views import goods_bp

app = Flask(__name__)

# 注册蓝图到应用
app.register_blueprint(user_bp)
app.register_blueprint(goods_bp)

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

访问http://localhost:5000/user/login(用户登录)、http://localhost:5000/goods/list(商品列表)即可验证,蓝图支持独立的模板/静态文件路径、错误处理等,是Flask模块化开发的核心。

8. 配置管理

Flask支持多种配置方式,核心是app.config(字典对象),推荐按环境(开发/测试/生产)分离配置:

(1)基本配置方式
python 复制代码
from flask import Flask

app = Flask(__name__)

# 方式1:直接设置
app.config['SECRET_KEY'] = '123456'
app.config['DEBUG'] = True

# 方式2:从字典加载
config = {
    'SECRET_KEY': '123456',
    'DEBUG': True
}
app.config.update(config)

# 方式3:从配置类加载(推荐,便于环境分离)
class DevelopmentConfig:
    DEBUG = True
    SECRET_KEY = 'dev-secret-key'

class ProductionConfig:
    DEBUG = False
    SECRET_KEY = 'prod-secret-key'  # 生产环境用随机生成的密钥

# 加载配置类
app.config.from_object(DevelopmentConfig)

# 方式4:从环境变量加载(生产环境推荐,避免硬编码敏感信息)
# app.config.from_envvar('FLASK_CONFIG_FILE')  # 读取环境变量指向的配置文件
9. 钩子函数(中间件)

Flask提供多个钩子函数,用于在请求处理的不同阶段执行自定义逻辑:

钩子函数 执行时机
before_request 每个请求处理前执行
after_request 每个请求处理后执行(无异常)
teardown_request 每个请求处理后执行(无论是否异常)
before_first_request 第一个请求处理前执行(Flask 2.0+已废弃,改用app.before_first_request_funcs)

示例:

python 复制代码
from flask import Flask, request

app = Flask(__name__)

# 请求处理前:记录请求信息
@app.before_request
def log_request():
    print(f'请求路径:{request.path},方法:{request.method}')

# 请求处理后:添加响应头
@app.after_request
def add_header(resp):
    resp.headers['X-Processed-By'] = 'Flask'
    return resp

# 请求处理完成后(无论是否异常):清理资源
@app.teardown_request
def teardown(exception):
    if exception:
        print(f'请求异常:{exception}')
    print('请求处理完成,清理资源')

@app.route('/')
def index():
    return 'Hello, Flask!'

if __name__ == '__main__':
    app.run(debug=True)
10. 常用扩展

Flask的核心功能有限,扩展是其生态的核心,以下是最常用的扩展:

  • Flask-SQLAlchemy :ORM框架,简化数据库操作(支持MySQL/PostgreSQL/SQLite等);
    安装:pip install flask-sqlalchemy
    示例:

    python 复制代码
    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    
    app = Flask(__name__)
    # 配置数据库连接(SQLite示例,文件型数据库)
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False  # 关闭修改跟踪(提升性能)
    db = SQLAlchemy(app)
    
    # 定义模型(对应数据库表)
    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)
    
        def __repr__(self):
            return f'<User {self.username}>'
    
    # 创建表(需在Python交互环境执行)
    # with app.app_context():
    #     db.create_all()
    
    @app.route('/add-user')
    def add_user():
        # 添加数据
        user = User(username='张三', email='zhangsan@example.com')
        db.session.add(user)
        db.session.commit()
        return '用户添加成功'
    
    @app.route('/users')
    def get_users():
        # 查询数据
        users = User.query.all()
        return f'所有用户:{users}'
    
    if __name__ == '__main__':
        app.run(debug=True)
  • Flask-WTF:封装WTForms,简化表单验证;

  • Flask-Login:处理用户登录、登出、会话管理;

  • Flask-Migrate:基于Alembic,实现数据库迁移(表结构修改);

  • Flask-CORS:解决跨域问题(前后端分离项目必备)。

11. 生产环境部署

开发环境的app.run()仅用于调试,生产环境需使用WSGI服务器 (Gunicorn)+ 反向代理(Nginx):

(1)使用Gunicorn启动Flask应用

安装:pip install gunicorn

创建wsgi.py

python 复制代码
from app import app

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

启动Gunicorn:

bash 复制代码
# 启动:workers是工作进程数(建议=CPU核心数*2+1),bind绑定地址和端口
gunicorn -w 4 -b 0.0.0.0:8000 wsgi:app
(2)配置Nginx反向代理

Nginx负责接收客户端请求,转发到Gunicorn,同时处理静态文件、负载均衡等:

nginx 复制代码
server {
    listen 80;
    server_name your-domain.com;  # 你的域名

    # 静态文件(Flask的static文件夹)
    location /static {
        alias /path/to/your/project/static;
    }

    # 转发动态请求到Gunicorn
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
12. 进阶
  • 上下文 :Flask有两种核心上下文------应用上下文(app_context)和请求上下文(request_context),request/session属于请求上下文,current_app/g属于应用上下文;
    • current_app:当前运行的应用实例;
    • g:全局临时存储,仅在当前请求有效,用于在钩子函数和视图函数间传递数据。
  • 信号 :Flask-Signals(需安装blinker),用于监听应用事件(如请求开始/结束、模板渲染完成等),实现解耦的事件通知;
  • 测试 :使用pytest+flask.test_client()编写单元测试,模拟请求并验证响应。

  1. Flask是轻量级Python Web框架,核心极简但可通过扩展实现复杂功能,适合小型项目/快速原型开发;
  2. 核心知识点包括:路由映射、请求/响应处理、Jinja2模板、Session/Cookie、蓝图(模块化)、配置管理、钩子函数;
  3. 生产环境需使用Gunicorn(WSGI服务器)+ Nginx(反向代理)部署,避免使用开发服务器;扩展是Flask生态的核心,Flask-SQLAlchemy、Flask-WTF等可大幅提升开发效率。
相关推荐
云深处@2 小时前
【C++11】特殊类&&单例模式
开发语言·c++
xinhuanjieyi2 小时前
python获取股票分红
chrome·python·elasticsearch
烟花落o2 小时前
算法的时间复杂度和空间复杂度
开发语言·数据结构·笔记·算法
西门吹-禅2 小时前
node js 性能处理
开发语言·javascript·ecmascript
我不是8神2 小时前
go-zero微服务框架总结
开发语言·微服务·golang
Ronaldinho Gaúch2 小时前
算法题中的日期问题
开发语言·c++·算法
喵手2 小时前
Python爬虫实战:小红书热门笔记爬虫实战 - 搜索关键词驱动的内容采集指南!
爬虫·python·爬虫实战·零基础python爬虫教学·小红书热门笔记·搜索关键词·采集小红书热门笔记数据
麦德泽特3 小时前
机器人赛事系统架构:基于UDT和MQTT的低延迟、高可靠通信
c语言·开发语言·安全·系统架构·机器人
nita张3 小时前
战略定位实战:案例分享与经验总结
大数据·人工智能·python