Flask 框架

Flask :轻量级 Python Web 框架

Flask 是一个基于 Python 的轻量级 Web 应用框架 ,遵循 "微框架"(Microframework) 理念,核心仅依赖两个库:Werkzeug (处理 HTTP 请求和路由)和Jinja2(模板引擎),其余功能通过丰富的扩展生态实现。它以简洁、灵活和可扩展性著称,适合从简单 API 到复杂 Web 应用的各种场景。


一、Flask 核心概念与特点

1.1 核心组件

组件 作用
Werkzeug WSGI 工具库,处理请求响应、路由匹配、会话管理
Jinja2 模板引擎,支持模板继承、变量替换、控制流
Click 命令行工具,用于创建和管理 Flask 应用

1.2 微框架理念

Flask 的 "微" 并非指功能少,而是指:

  • 核心代码精简,只保留 Web 开发的最基础功能
  • 不强制使用特定工具或库,给予开发者完全自由
  • 不内置 ORM、用户认证、表单处理等功能,通过扩展按需添加
  • 遵循 "约定优于配置",但保持高度灵活性

1.3 主要特点

  • 轻量级:核心代码少,学习曲线平缓,适合快速上手
  • 灵活性:可根据需求选择组件,自由定制架构
  • 可扩展:拥有丰富的官方和社区扩展,覆盖几乎所有 Web 开发需求
  • RESTful 友好:内置支持 RESTful API 开发,可轻松构建 API 服务
  • 开发效率高:内置开发服务器和调试器,支持热重载
  • 测试简单:内置测试客户端,便于编写单元测试和集成测试

二、安装与环境配置

2.1 基本安装

bash 复制代码
# 创建虚拟环境(推荐)
python -m venv venv
source venv/bin/activate  # Linux/Mac
venv\Scripts\activate     # Windows

# 安装Flask
pip install flask

2.2 第一个 Flask 应用(Hello World)

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

app = Flask(__name__)  # 创建Flask应用实例

@app.route('/')        # 路由装饰器,绑定URL路径到视图函数
def hello_world():
    return 'Hello, Flask!'  # 返回响应

if __name__ == '__main__':
    app.run(debug=True)  # 运行开发服务器,开启调试模式

运行应用:

bash 复制代码
python app.py
# 访问 http://127.0.0.1:5000

三、Flask 核心功能详解

3.1 路由系统

路由是 Flask 的核心,用于将 URL 路径映射到视图函数。

3.1.1 基础路由
python 复制代码
# 静态路由
@app.route('/about')
def about():
    return 'About Page'

# 动态路由(字符串参数)
@app.route('/user/<username>')
def show_user(username):
    return f'User: {username}'

# 动态路由(指定类型)
@app.route('/post/<int:post_id>')  # int、float、path(接受斜杠)
def show_post(post_id):
    return f'Post ID: {post_id}'
3.1.2 HTTP 方法

默认只支持 GET 方法,可通过methods参数指定多种 HTTP 方法:

python 复制代码
from flask import request

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        # 处理表单提交
        username = request.form['username']
        password = request.form['password']
        return f'Login attempt for {username}'
    else:
        # 显示登录表单
        return '''
            <form method="post">
                Username: <input type="text" name="username"><br>
                Password: <input type="password" name="password"><br>
                <input type="submit" value="Login">
            </form>
        '''
3.1.3 URL 构建(url_for)

使用url_for()函数根据视图函数名生成 URL,避免硬编码:

python 复制代码
from flask import url_for

@app.route('/')
def index():
    # 生成about页面的URL
    about_url = url_for('about')
    # 生成带参数的URL
    user_url = url_for('show_user', username='Alice')
    return f'''
        <a href="{about_url}">About</a><br>
        <a href="{user_url}">User Alice</a>
    '''

3.2 视图函数与响应

3.2.1 视图函数返回值类型

视图函数可以返回多种类型的响应:

python 复制代码
# 1. 字符串(自动包装为Response对象)
@app.route('/string')
def return_string():
    return 'Hello, Flask!'

# 2. 元组(响应内容, 状态码, 响应头)
@app.route('/tuple')
def return_tuple():
    return 'Not Found', 404, {'Content-Type': 'text/plain'}

# 3. Response对象(完全控制响应)
from flask import Response
@app.route('/response')
def return_response():
    response = Response('Custom Response', status=200)
    response.headers['X-Custom-Header'] = 'Flask'
    return response

# 4. JSON数据(自动设置Content-Type为application/json)
@app.route('/json')
def return_json():
    return {'name': 'Alice', 'age': 30}
3.2.2 重定向与错误处理
python 复制代码
from flask import redirect, abort

# 重定向
@app.route('/old')
def old_page():
    return redirect(url_for('new_page'))

@app.route('/new')
def new_page():
    return 'This is the new page'

# 错误处理
@app.errorhandler(404)
def page_not_found(error):
    return 'Page not found!', 404

# 主动触发错误
@app.route('/error')
def trigger_error():
    abort(404)  # 立即返回404错误

3.3 请求处理(request 对象)

Flask 通过request对象封装客户端请求信息,该对象是上下文局部变量,仅在请求处理期间有效:

python 复制代码
from flask import request

@app.route('/request-info')
def request_info():
    return f'''
        Method: {request.method}<br>
        URL: {request.url}<br>
        Args: {request.args}<br>  # 查询参数(?key=value)
        Form: {request.form}<br>  # 表单数据
        Headers: {request.headers.get('User-Agent')}<br>
        Cookies: {request.cookies.get('session_id')}<br>
    '''

3.4 模板系统(Jinja2)

Flask 集成 Jinja2 模板引擎,支持动态生成 HTML 页面。

3.4.1 基本用法

创建模板文件(默认存放在templates目录)

html 复制代码
<!-- templates/index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
    <h1>Hello, {{ name }}!</h1>
    {% if user %}
        <p>Welcome back, {{ user.username }}!</p>
    {% else %}
        <p>Please log in.</p>
    {% endif %}
    
    <ul>
        {% for item in items %}
            <li>{{ item }}</li>
        {% endfor %}
    </ul>
</body>
</html>

渲染模板

python 复制代码
from flask import render_template

@app.route('/template')
def render_template_example():
    return render_template(
        'index.html',
        title='Flask Template Demo',
        name='Alice',
        user={'username': 'alice123'},
        items=['Apple', 'Banana', 'Cherry']
    )
3.4.2 模板继承

Jinja2 支持模板继承,减少代码重复:

html 复制代码
<!-- templates/base.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}My App{% endblock %}</title>
</head>
<body>
    <header>{% block header %}<h1>My App</h1>{% endblock %}</header>
    <main>{% block content %}{% endblock %}</main>
    <footer>{% block footer %}© 2026 My App{% endblock %}</footer>
</body>
</html>

<!-- templates/home.html -->
{% extends "base.html" %}

{% block title %}Home - My App{% endblock %}

{% block content %}
    <p>Welcome to the home page!</p>
{% endblock %}

3.5 会话管理(session 对象)

Flask 使用session对象实现用户会话,基于加密 Cookie:

python 复制代码
from flask import session, redirect, url_for, request

app.secret_key = 'your-secret-key-here'  # 必须设置密钥用于加密会话数据

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        session['username'] = username  # 存储会话数据
        return redirect(url_for('dashboard'))
    return '''
        <form method="post">
            Username: <input type="text" name="username"><br>
            <input type="submit" value="Login">
        </form>
    '''

@app.route('/dashboard')
def dashboard():
    if 'username' in session:
        return f'Welcome, {session["username"]}! <a href="/logout">Logout</a>'
    return redirect(url_for('login'))

@app.route('/logout')
def logout():
    session.pop('username', None)  # 删除会话数据
    return redirect(url_for('login'))

四、Flask 扩展生态

Flask 的强大之处在于其丰富的扩展生态,以下是常用扩展:

扩展名称 功能
Flask-SQLAlchemy ORM 工具,支持 SQLite、MySQL、PostgreSQL 等数据库
Flask-WTF 表单处理与验证,集成 WTForms
Flask-Login 用户认证系统,管理用户登录状态
Flask-Mail 邮件发送功能
Flask-RESTful 简化 RESTful API 开发
Flask-Babel 国际化与本地化支持
Flask-Admin 快速创建管理后台
Flask-CORS 处理跨域资源共享 (CORS) 问题

4.1 扩展使用示例(Flask-SQLAlchemy)

python 复制代码
# 安装扩展
pip install flask-sqlalchemy

# 应用代码
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///mydb.db'  # SQLite数据库
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 shell中执行)
with app.app_context():
    db.create_all()

# 数据库操作示例
@app.route('/add-user/<username>/<email>')
def add_user(username, email):
    new_user = User(username=username, email=email)
    db.session.add(new_user)
    db.session.commit()
    return f'User {username} added!'

@app.route('/users')
def get_users():
    users = User.query.all()
    return '<br>'.join([f'{user.username}: {user.email}' for user in users])

五、Flask 高级特性

5.1 应用工厂模式

应用工厂模式允许创建多个应用实例,适合测试和配置不同环境:

py 复制代码
# app/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def create_app(config_name='development'):
    app = Flask(__name__)
    
    # 根据配置名称加载不同配置
    if config_name == 'development':
        app.config.from_object('config.DevelopmentConfig')
    elif config_name == 'production':
        app.config.from_object('config.ProductionConfig')
    
    db.init_app(app)  # 初始化扩展
    
    # 注册蓝图
    from app.main import bp as main_bp
    app.register_blueprint(main_bp)
    
    return app

# config.py
class Config:
    SECRET_KEY = 'your-secret-key'
    SQLALCHEMY_TRACK_MODIFICATIONS = False

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

class ProductionConfig(Config):
    DEBUG = False
    SQLALCHEMY_DATABASE_URI = 'postgresql://user:password@localhost/prod_db'

5.2 蓝图(Blueprints)

蓝图用于组织大型应用的路由和视图,实现模块化开发:

python 复制代码
# app/main/__init__.py
from flask import Blueprint

bp = Blueprint('main', __name__)

# app/main/routes.py
from flask import render_template
from app.main import bp

@bp.route('/')
def index():
    return render_template('index.html')

@bp.route('/about')
def about():
    return render_template('about.html')

5.3 上下文管理器

Flask 有两种主要上下文:

  • 应用上下文 :存储应用级数据(current_app, g
  • 请求上下文 :存储请求级数据(request, session
python 复制代码
from flask import Flask, current_app, g

app = Flask(__name__)
app.config['DATABASE'] = 'mydb.db'

def get_db():
    if 'db' not in g:
        # 假设这里创建数据库连接
        g.db = f"Connected to {current_app.config['DATABASE']}"
    return g.db

@app.route('/db')
def db_info():
    return get_db()

六、Flask 部署与最佳实践

6.1 部署选项

Flask 开发服务器仅用于开发环境,生产环境需要使用专业 WSGI 服务器:

服务器 特点
Gunicorn 纯 Python WSGI 服务器,简单易用
uWSGI 高性能 WSGI 服务器,支持多种协议
Gevent 基于协程的异步服务器,适合高并发

部署步骤:

  1. 安装生产服务器:pip install gunicorn
  2. 创建启动脚本:gunicorn -w 4 -b 0.0.0.0:8000 "app:create_app()"
  3. 配合 Nginx 作为反向代理,处理静态文件和负载均衡

6.2 最佳实践

  1. 项目结构:使用蓝图和应用工厂模式组织代码

  2. 环境分离:开发、测试、生产环境使用不同配置

  3. 安全措施

    • 设置强密钥(SECRET_KEY
    • 启用 CSRF 保护(Flask-WTF)
    • 验证用户输入,防止 SQL 注入和 XSS 攻击
    • 使用 HTTPS
  4. 性能优化

    • 使用缓存(Flask-Caching)
    • 数据库查询优化
    • 异步任务处理(Celery)
  5. 日志记录:配置完善的日志系统,便于问题排查

七、Flask vs Django:如何选择

对比项 Flask Django
设计理念 微框架,轻量级,灵活自由 全栈框架,"电池已包含",约定优于配置
内置功能 仅核心功能,其他通过扩展实现 内置 ORM、Admin、认证、表单等全套功能
灵活性 极高,可自由选择组件 中等,遵循 Django 约定
学习曲线 平缓,适合初学者 陡峭,概念较多
适用场景 小型应用、API 服务、微服务、快速原型 中大型应用、CMS、电商平台、企业级系统

八、快速入门:创建 RESTful API 示例

以下是一个完整的 Flask RESTful API 示例,使用 Flask-RESTful 扩展:

python 复制代码
# 安装扩展
pip install flask flask-restful flask-sqlalchemy

# app.py
from flask import Flask, request
from flask_restful import Api, Resource, fields, marshal_with
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///api.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
api = Api(app)
db = SQLAlchemy(app)

# 模型定义
class Task(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(80), nullable=False)
    description = db.Column(db.String(200))
    done = db.Column(db.Boolean, default=False)

# 序列化字段
resource_fields = {
    'id': fields.Integer,
    'title': fields.String,
    'description': fields.String,
    'done': fields.Boolean
}

# API资源
class TaskList(Resource):
    @marshal_with(resource_fields)
    def get(self):
        tasks = Task.query.all()
        return tasks
    
    @marshal_with(resource_fields)
    def post(self):
        data = request.json
        new_task = Task(title=data['title'], description=data.get('description'))
        db.session.add(new_task)
        db.session.commit()
        return new_task, 201

class TaskResource(Resource):
    @marshal_with(resource_fields)
    def get(self, task_id):
        task = Task.query.get_or_404(task_id)
        return task
    
    @marshal_with(resource_fields)
    def put(self, task_id):
        task = Task.query.get_or_404(task_id)
        data = request.json
        task.title = data.get('title', task.title)
        task.description = data.get('description', task.description)
        task.done = data.get('done', task.done)
        db.session.commit()
        return task
    
    def delete(self, task_id):
        task = Task.query.get_or_404(task_id)
        db.session.delete(task)
        db.session.commit()
        return '', 204

# 注册资源
api.add_resource(TaskList, '/tasks')
api.add_resource(TaskResource, '/tasks/<int:task_id>')

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

if __name__ == '__main__':
    app.run(debug=True)
相关推荐
橘子编程2 小时前
编程语言全指南:从C到Rust
java·c语言·开发语言·c++·python·rust·c#
我送炭你添花2 小时前
边走边聊 Python 3.8:Win7 从入门到高手(目录)
开发语言·python
w_t_y_y2 小时前
工具篇(一)机器学习常用的python包
开发语言·python·信息可视化
徒 花2 小时前
Python知识学习07
windows·python·学习
鬼先生_sir2 小时前
SpringCloud-openFeign(服务调用)
后端·spring·spring cloud
A懿轩A2 小时前
【2026 最新】Python 下载与安装:在 macOS 下使用 Homebrew 和 pyenv 完美管理多版本 Python
python·macos·mac
Freak嵌入式2 小时前
小作坊 GitHub 协作闭环:fork-sync-dev-pr-merge 实战指南
python·github·远程工作·代码规范·micropython·协作
IT_陈寒2 小时前
Java线程池用完不关闭?小心内存泄漏找上门
前端·人工智能·后端
跟着珅聪学java2 小时前
在 Java 中处理 JSON 去除空 children数组,可以使用 Jackson 库。这里有几种实现方式
开发语言·windows·python