第135集 Flask框架基础

1. Flask框架简介

Flask是一个轻量级的Python Web框架,以其简洁、灵活和可扩展的特性而闻名。它由Armin Ronacher于2010年创建,基于Werkzeug WSGI工具包和Jinja2模板引擎。

1.1 Flask的历史

  • 2010年4月:Flask首次发布
  • 2010年6月:发布Flask 0.1版本
  • 2018年4月:发布Flask 1.0版本
  • 2020年5月:发布Flask 1.1版本
  • 2023年1月:发布Flask 2.3版本

1.2 Flask的特点

  • 轻量级:核心功能简洁,只包含必要的组件
  • 灵活性:允许开发者选择自己喜欢的扩展和工具
  • 可扩展:拥有丰富的第三方扩展生态系统
  • 简单易学:API设计直观,上手难度低
  • 支持RESTful:适合构建RESTful API
  • 内置开发服务器:方便开发和测试
  • Jinja2模板引擎:强大的模板渲染能力
  • Werkzeug WSGI工具包:提供了请求处理、路由等核心功能

1.3 Flask与其他框架的比较

特性 Flask Django Bottle
类型 微框架 全栈框架 微框架
灵活性
内置功能
学习曲线 平缓 陡峭 平缓
社区支持 极大
适合项目 小型到中型 大型 小型

2. Flask的安装

2.1 安装Flask

使用pip安装Flask非常简单:

# 安装最新版本
pip install flask

# 安装特定版本
pip install flask==2.3.3

2.2 验证安装

安装完成后,可以通过以下方式验证:

import flask
print(flask.__version__)
# 输出: 2.3.3

2.3 虚拟环境

推荐在虚拟环境中安装Flask,以避免依赖冲突:

# 创建虚拟环境
python -m venv venv

# 激活虚拟环境(Windows)
venv\Scripts\activate

# 激活虚拟环境(Linux/Mac)
source venv/bin/activate

# 安装Flask
pip install flask

3. Flask第一个应用

3.1 创建基本结构

创建一个简单的Flask应用,只需要几行代码:

# app.py
from flask import Flask

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

# 定义路由和视图函数
@app.route('/')
def hello_world():
    return 'Hello, Flask!'

# 启动应用
if __name__ == '__main__':
    app.run()

3.2 运行应用

python app.py

运行后,你会看到类似以下输出:

 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

现在可以在浏览器中访问 http://127.0.0.1:5000/ ,看到"Hello, Flask!"的输出。

3.3 启用调试模式

调试模式下,Flask会自动重载代码变化,并提供详细的错误信息:

# 方式1:在app.run()中设置
app.run(debug=True)

# 方式2:通过环境变量设置
export FLASK_ENV=development  # Linux/Mac
export FLASK_APP=app.py
flask run

# Windows
sets FLASK_ENV=development
sets FLASK_APP=app.py
flask run

4. Flask应用的基本结构

一个典型的Flask应用结构如下:

myapp/
├── app.py                 # 主应用文件
├── templates/             # 模板文件目录
│   ├── index.html
│   └── about.html
├── static/                # 静态文件目录
│   ├── css/
│   │   └── style.css
│   ├── js/
│   │   └── script.js
│   └── images/
│       └── logo.png
├── venv/                  # 虚拟环境
└── requirements.txt       # 依赖列表

4.1 主应用文件

主应用文件通常包含Flask应用实例的创建、路由定义和配置等。

4.2 模板目录

存放HTML模板文件,使用Jinja2模板引擎渲染。

4.3 静态目录

存放CSS、JavaScript、图片等静态资源文件。

4.4 依赖列表

使用pip freeze > requirements.txt命令生成,包含项目的所有依赖包。

5. Flask路由

路由是指将URL与视图函数关联起来的机制。

5.1 基本路由

使用@app.route()装饰器定义路由:

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

@app.route('/about')
def about():
    return '关于我们'

5.2 动态路由

可以在路由中使用变量,用尖括号包裹:

@app.route('/user/<username>')
def show_user_profile(username):
    return f'用户 {username}'

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

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

5.3 支持的转换器

  • string:默认类型,接受任何不包含斜杠的文本
  • int:接受正整数
  • float:接受正浮点数
  • path:类似string,但可以包含斜杠
  • uuid:接受UUID字符串

5.4 HTTP方法

默认情况下,路由只接受GET请求,可以通过methods参数指定允许的HTTP方法:

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        # 处理登录表单提交
        username = request.form['username']
        password = request.form['password']
        return f'登录用户: {username}'
    else:
        # 显示登录表单
        return '显示登录表单'

6. Flask请求处理

6.1 请求对象

Flask提供了request对象来访问请求数据:

from flask import request

@app.route('/login', methods=['POST'])
def login():
    # 获取表单数据
    username = request.form['username']  # POST请求表单数据
    password = request.form['password']
    
    # 获取查询参数
    next_url = request.args.get('next')  # GET请求查询参数
    
    # 获取请求头
    user_agent = request.headers.get('User-Agent')
    
    # 获取JSON数据
    if request.is_json:
        data = request.get_json()
    
    return f'登录用户: {username}'

6.2 响应对象

可以返回不同类型的响应:

from flask import Response, jsonify

# 返回字符串
@app.route('/')
def index():
    return 'Hello World'

# 返回元组 (响应内容, 状态码, 响应头)
@app.route('/not_found')
def not_found():
    return 'Not Found', 404

# 返回Response对象
@app.route('/custom_response')
def custom_response():
    response = Response('Custom Response', status=200, mimetype='text/plain')
    response.headers['X-Custom-Header'] = 'value'
    return response

# 返回JSON
@app.route('/api/data')
def api_data():
    data = {'name': '张三', 'age': 20}
    return jsonify(data)

6.3 Cookie和Session

from flask import make_response

@app.route('/set_cookie')
def set_cookie():
    response = make_response('设置Cookie')
    response.set_cookie('username', '张三', max_age=3600)  # 1小时
    return response

@app.route('/get_cookie')
def get_cookie():
    username = request.cookies.get('username')
    return f'Cookie中的用户名: {username}'

Session

Session使用密钥签名,需要设置SECRET_KEY:

app.secret_key = 'your-secret-key'

from flask import session

@app.route('/set_session')
def set_session():
    session['username'] = '张三'
    return '设置Session'

@app.route('/get_session')
def get_session():
    username = session.get('username')
    return f'Session中的用户名: {username}'

@app.route('/clear_session')
def clear_session():
    session.pop('username', None)
    return '清除Session'

7. Flask模板

7.1 渲染模板

使用render_template()函数渲染模板:

from flask import render_template

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

@app.route('/user/<username>')
def show_user(username):
    return render_template('user.html', name=username, age=20)

7.2 模板变量

在模板中使用{{ 变量名 }}来输出变量:

<!DOCTYPE html>
<html>
<head>
    <title>用户信息</title>
</head>
<body>
    <h1>欢迎, {{ name }}!</h1>
    <p>年龄: {{ age }}</p>
</body>
</html>

7.3 模板控制结构

条件语句

{% if age >= 18 %}
    <p>成年人</p>
{% elif age >= 13 %}
    <p>青少年</p>
{% else %}
    <p>儿童</p>
{% endif %}

循环语句

<ul>
    {% for fruit in fruits %}
        <li>{{ fruit }}</li>
    {% endfor %}
</ul>

{% macro input(name, value='', type='text') %}
    <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}

{{ input('username') }}
{{ input('password', type='password') }}

继承

<!-- base.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}默认标题{% endblock %}</title>
</head>
<body>
    <div id="content">
        {% block content %}{% endblock %}
    </div>
</body>
</html>

<!-- index.html -->
{% extends "base.html" %}

{% block title %}首页{% endblock %}

{% block content %}
    <h1>首页内容</h1>
{% endblock %}

7.4 过滤器

{{ name|capitalize }}  <!-- 首字母大写 -->
{{ message|safe }}  <!-- 安全输出 -->
{{ text|truncate(50) }}  <!-- 截断文本 -->
{{ price|format("%.2f") }}  <!-- 格式化数字 -->
{{ list|join(", ") }}  <!-- 连接列表 -->

8. Flask静态文件

8.1 引用静态文件

使用url_for()函数生成静态文件的URL:

<!-- 引用CSS -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">

<!-- 引用JavaScript -->
<script src="{{ url_for('static', filename='js/script.js') }}"></script>

<!-- 引用图片 -->
<img src="{{ url_for('static', filename='images/logo.png') }}" alt="Logo">

8.2 自定义静态目录

可以自定义静态目录的位置:

app = Flask(__name__, static_folder='assets')

9. Flask扩展

Flask拥有丰富的第三方扩展,以下是一些常用的扩展:

9.1 数据库扩展

  • Flask-SQLAlchemy:SQLAlchemy的Flask集成,用于数据库操作
  • Flask-Migrate:数据库迁移工具
  • Flask-MongoEngine:MongoDB的Flask集成

9.2 用户认证

  • Flask-Login:用户会话管理
  • Flask-Security:用户认证和授权
  • Flask-JWT-Extended:JWT认证

9.3 表单处理

  • Flask-WTF:WTForms的Flask集成,用于表单处理

9.4 API开发

  • Flask-RESTful:用于构建RESTful API
  • Flask-RESTPlus:提供API文档的RESTful扩展

9.5 缓存

  • Flask-Cache:缓存支持

9.6 邮件

  • Flask-Mail:邮件发送功能

10. Flask配置

10.1 配置方法

直接设置

app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'your-secret-key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'

使用配置文件

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

class DevelopmentConfig(Config):
    DEBUG = True

class ProductionConfig(Config):
    SECRET_KEY = 'production-secret-key'

# app.py
app = Flask(__name__)
app.config.from_object('config.DevelopmentConfig')

使用环境变量

import os
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'default-key')

10.2 常用配置项

  • DEBUG:是否启用调试模式
  • SECRET_KEY:用于加密会话数据
  • TESTING:是否启用测试模式
  • JSON_SORT_KEYS:是否对JSON响应中的键进行排序
  • SERVER_NAME:服务器名称
  • PERMANENT_SESSION_LIFETIME:会话过期时间

11. Flask错误处理

11.1 自定义错误页面

使用@app.errorhandler()装饰器定义错误处理函数:

@app.errorhandler(404)
def page_not_found(error):
    return render_template('404.html'), 404

@app.errorhandler(500)
def internal_server_error(error):
    return render_template('500.html'), 500

@app.errorhandler(403)
def forbidden(error):
    return render_template('403.html'), 403

11.2 异常处理

可以捕获特定的异常:

try:
    # 可能出错的代码
except Exception as e:
    # 处理异常
    return render_template('error.html', error=e), 500

12. Flask最佳实践

12.1 项目结构

使用蓝图组织代码,提高代码的可维护性:

myapp/
├── app/
│   ├── __init__.py
│   ├── main/
│   │   ├── __init__.py
│   │   ├── routes.py
│   │   └── forms.py
│   ├── auth/
│   │   ├── __init__.py
│   │   ├── routes.py
│   │   └── forms.py
│   ├── models.py
│   ├── config.py
│   └── utils.py
├── migrations/
├── tests/
├── venv/
├── run.py
└── requirements.txt

12.2 使用蓝图

蓝图允许将应用分解为多个模块:

# app/main/__init__.py
from flask import Blueprint

main = Blueprint('main', __name__)

from . import routes

# app/auth/__init__.py
from flask import Blueprint

auth = Blueprint('auth', __name__)

from . import routes

# app/__init__.py
from flask import Flask
from .main import main as main_blueprint
from .auth import auth as auth_blueprint

def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(config[config_name])
    
    app.register_blueprint(main_blueprint, url_prefix='/')
    app.register_blueprint(auth_blueprint, url_prefix='/auth')
    
    return app

12.3 安全性

  • 不要在生产环境中启用调试模式
  • 使用强密码作为SECRET_KEY
  • 对用户输入进行验证和过滤
  • 使用HTTPS协议
  • 避免SQL注入
  • 正确处理错误信息,不要泄露敏感信息

12.4 性能优化

  • 使用缓存减少数据库查询
  • 使用异步处理耗时操作
  • 优化模板渲染
  • 使用CDN加速静态文件
  • 启用gzip压缩

13. 总结

Flask是一个轻量级、灵活、可扩展的Python Web框架,适合构建各种规模的Web应用。它的核心特点是简洁和灵活,允许开发者根据自己的需求选择合适的工具和扩展。

本集主要介绍了Flask的基本概念、安装、第一个应用、路由、请求处理、模板、静态文件、配置和最佳实践等内容。通过学习这些基础知识,你已经可以开始使用Flask构建简单的Web应用了。

在后续的学习中,我们将深入学习Flask的路由与视图、模板、表单处理、数据库集成等高级功能,以及如何使用Flask构建完整的Web应用。

« 上一篇 JavaScript基础 下一篇 » Flask路由与视图