1.Flask简介
2.Flask安装
Flask是一个使用Python编写的轻量级Web应用框架。它基于Werkzeug WSGI工具箱和Jinja2模板引擎。Flask使用简单,易于扩展,适合小型项目和快速开发。
- 轻量且高效:核心简洁,启动迅速,资源占用低
- 灵活性:不强制特定项目结构或组件选择
- 易于学习:API设计直观,学习曲线平缓
- 可扩展性:通过丰富的扩展生态系统增强功能
- 强大的路由系统:支持URL变量和HTTP方法
- 内置开发服务器:便于本地测试和开发
- RESTful支持:轻松构建符合REST规范的API
Flask和Django是Python Web开发中最流行的两个框架,它们各有优势:
| 特性 | Flask | Django |
|---|---|---|
| 架构理念 | 微框架,灵活定制 | 全能框架,内置齐全 |
| 学习曲线 | 较低,容易上手 | 较高,概念较多 |
| 项目规模 | 适合小到中型项目 | 适合中到大型项目 |
| 自由度 | 高,可自由选择组件 | 低,遵循"Django方式" |
| 数据库支持 | 通过扩展支持 | ORM内置 |
| 管理后台 | 需要自行实现或使用扩展 | 内置强大的管理后台 |
PS: Markdown语法:表格对齐方式
使用 | 符号分隔列
使用 - 符号创建表头分隔线
列对齐可以通过在分隔线中使用 : 来实现:
:--- 左对齐
:---: 居中对齐
---: 右对齐
虚拟环境(venv)安装flask:
py -3.12 -m venv venv
.\venv\Scripts\activate(激活)
deactivate(退出)
# 设置清华源
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
# 查看当前 pip 源
pip config list
pip install flask
pip install -e . 是将项目安装为可编辑模式(editable mode), 文件夹(包含__init__.py)会编译成一个包,代码中可绝对引用
my_flask_app/
│
├── app/
│ ├── __init__.py # 应用工厂
│ ├── routes/ # 路由定义
│ │ ├── __init__.py
│ │ ├── main.py
│ │ └── auth.py
│ ├── models/ # 数据模型
│ │ ├── __init__.py
│ │ └── user.py
│ ├── templates/ # 模板文件
│ │ ├── layout.html
│ │ └── home.html
│ └── static/ # 静态文件
│ ├── css/
│ └── js/
│
├── config.py # 配置文件
├── requirements.txt
├── migrations/
│ └── ...
└── run.py
Flask 路由是 Web 应用程序中将 URL 映射到 Python 函数的机制。
Flask 路由是 Flask 应用的核心部分,用于处理不同 URL 的请求,并将请求的处理委托给相应的视图函数。
- 定义路由:使用 @app.route('/path') 装饰器定义 URL 和视图函数的映射。
- 路由参数:通过动态部分在 URL 中传递参数。
- 路由规则:使用类型转换器指定 URL 参数的类型。
- 请求方法:指定允许的 HTTP 请求方法。
- 路由函数返回:视图函数可以返回不同类型的响应。
- 静态文件和模板:管理静态文件和动态渲染 HTML 模板。
- 路由优先级:确保路由顺序正确,以避免意外的匹配结果。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return 'Welcome to the Home Page!'
@app.route('/greet/<name>')
def greet(name):
return f'Hello, {name}!'
参数匹配规则:
字符串(默认): 匹配任意字符串。
整数(<int:name>): 匹配整数值。
浮点数(<float:value>): 匹配浮点数值。
路径(<path:name>): 匹配任意字符,包括斜杠 /。
@app.route('/files/<path:filename>')
def serve_file(filename):
return f'Serving file: {filename}'
路由转换
int: 匹配整数。 float: 匹配浮点数。 path: 匹配任意路径,包括斜杠。
@app.route('/items/<int:item_id>/details')
def item_details(item_id):
return f'Item details for item ID: {item_id}'
<int:item_id>:将 URL 中的 item_id 转换为整数。
路由函数返回
视图函数可以返回多种类型的响应:
- 字符串:返回纯文本响应。
- HTML:返回 HTML 页面。
- JSON:返回 JSON 数据。
- Response 对象:自定义响应。
from flask import jsonify, Response
@app.route('/json')
def json_response():
data = {'key': 'value'}
return jsonify(data)
@app.route('/custom')
def custom_response():
response = Response('Custom response with headers', status=200)
response.headers['X-Custom-Header'] = 'Value'
return response
jsonify(data):将字典转换为 JSON 响应。
Response('Custom response with headers', status=200):创建自定义响应对象。
静态文件和模板 静态文件(如 CSS、JavaScript、图片)可以通过 static 路由访问。模板文件则通过 templates 文件夹组织,用于渲染 HTML 页面。
<link rel="stylesheet" href="proxy.php?url=https%3A%2F%2Fgithub.com.%2F%7B%7B+url_for%28"static', filename='style.css') }}">
模板文件渲染:
from flask import render_template
@app.route('/hello/<name>')
def hello(name):
return render_template('hello.html', name=name)
模板文件 (templates/hello.html):
<!DOCTYPE html>
<html>
<head>
<title>Hello</title>
</head>
<body>
<h1>Hello, {{ name }}!</h1>
</body>
</html>路由优先级 Flask 按照定义的顺序匹配路由,第一个匹配成功的路由将被处理。确保更具体的路由放在更一般的路由之前。
@app.route('/user/<int:user_id>')
def user_profile(user_id):
return f'User ID: {user_id}'
@app.route('/user')
def user_list():
return 'User List'
视图函数是 Flask 应用中的核心部分,它负责处理请求并生成响应。
视图函数与路由紧密结合,通过路由将 URL 映射到具体的视图函数。
- 定义视图函数:视图函数是处理请求并返回响应的核心功能。
- 接收请求数据:使用 request 对象获取 URL 参数、表单数据、查询参数等。
- 返回响应:可以返回字符串、HTML、JSON 或自定义响应对象。
- 处理请求和响应:使用 request 对象和 make_response 来处理请求和生成自定义响应。
- 处理错误:视图函数内处理异常或使用 Flask 的错误处理机制。
- 视图函数的装饰器:使用 @app.before_request、@app.after_request 等装饰器处理请求前后逻辑。 视图函数返回的状态码:可以指定 HTTP 状态码来表示请求的处理结果。
1.定义视图函数
视图函数是一个普通的 Python 函数,它接收请求并返回响应。视图函数通常与路由配合使用,通过装饰器将 URL 映射到视图函数。
2. 接收请求数据 视图函数可以接收不同类型的请求数据,包括 URL 参数、表单数据、查询参数等。
获取 URL 参数:
@app.route('/greet/<name>')
def greet(name):
return f'Hello, {name}!'
<name> 是一个 URL 参数,传递到视图函数 greet。
获取表单数据:
from flask import request
@app.route('/submit', methods=['POST'])
def submit():
username = request.form.get('username')
return f'Form submitted by {username}!'
request.form.get('username'):获取 POST 请求中表单数据的 username 字段。
获取查询参数:
@app.route('/search')
def search():
query = request.args.get('query')
return f'Search results for: {query}'
request.args.get('query'):获取 GET 请求中的查询参数 query。
3. 返回响应
视图函数可以返回多种类型的响应,包括字符串、HTML、JSON、或自定义响应对象。
返回字符串:
@app.route('/message')
def message():
return 'This is a simple message.'
返回 HTML 模板:
from flask import render_template
@app.route('/hello/<name>')
def hello(name):
return render_template('hello.html', name=name)
render_template('hello.html', name=name):渲染 HTML 模板 hello.html,并将 name 变量传递给模板。
返回 JSON 数据:
from flask import jsonify
@app.route('/api/data')
def api_data():
data = {'key': 'value'}
return jsonify(data)
jsonify(data):将 Python 字典转换为 JSON 响应。
返回自定义响应对象:
from flask import Response
@app.route('/custom')
def custom_response():
response = Response('Custom response with headers', status=200)
response.headers['X-Custom-Header'] = 'Value'
return response
Response('Custom response with headers', status=200):创建自定义响应对象,并设置响应头。
4. 处理请求和响应
视图函数可以访问请求对象,并根据请求数据生成响应。可以使用 request 对象来获取请求的信息,使用 make_response 来创建自定义响应。
使用 request 对象:
from flask import request
@app.route('/info')
def info():
user_agent = request.headers.get('User-Agent')
return f'Your user agent is {user_agent}'
request.headers.get('User-Agent'):获取请求头中的 User-Agent 信息。
使用 make_response:
from flask import make_response
@app.route('/header')
def custom_header():
response = make_response('Response with custom header')
response.headers['X-Custom-Header'] = 'Value'
return response
make_response('Response with custom header'):创建响应对象并设置自定义头信息。
5. 处理错误
可以在视图函数中处理异常或错误,或者通过 Flask 提供的错误处理机制来处理应用中的错误。
在视图函数中处理错误:
@app.route('/divide/<int:x>/<int:y>')
def divide(x, y):
try:
result = x / y
return f'Result: {result}'
except ZeroDivisionError:
return 'Error: Division by zero', 400
使用 try-except 语句处理除零错误,并返回自定义错误消息和状态码。
全局错误处理:
@app.errorhandler(404)
def not_found(error):
return 'Page not found', 404
@app.errorhandler(404):定义处理 404 错误的函数。
6. 视图函数的装饰器
除了 @app.route,Flask 还支持其他装饰器,用于实现更复杂的功能。 示例: @app.before_request:在每个请求处理之前运行的函数。 @app.after_request:在每个请求处理之后运行的函数。 @app.teardown_request:在请求结束后运行的函数,用于清理工作。 示例装饰器使用:
@app.before_request
def before_request():
print('Before request')
@app.after_request
def after_request(response):
print('After request')
return response
@app.teardown_request
def teardown_request(exception):
print('Teardown request')
模板是包含占位符的 HTML 文件。 Flask 使用 Jinja2 模板引擎来处理模板渲染。模板渲染允许你将动态内容插入到 HTML 页面中,使得应用能够生成动态的网页内容。
- 创建模板:将 HTML 文件放在 templates 文件夹中,使用 Jinja2 占位符。
- 渲染模板:使用 render_template 函数在视图函数中渲染模板。
- 模板继承:创建基础模板,允许其他模板继承和扩展。
- 控制结构:使用条件语句和循环在模板中控制逻辑。
- 过滤器:使用过滤器格式化变量数据。
- 宏和模板包含:创建和使用宏以及模板包含,提高模板的复用性。
- 安全性:Jinja2 默认对模板变量进行自动转义以防止 XSS 攻击。
- 模板上下文:将数据传递给模板,并在模板中使用这些数据。
1. 创建模板
模板文件通常放在项目的 templates 文件夹中。Flask 会自动从这个文件夹中查找模板文件。 templates/index.html 文件代码:
<!DOCTYPE html>
<html>
<head>
<title>Welcome</title>
</head>
<body>
<h1>{{ title }}</h1>
<p>Hello, {{ name }}!</p>
</body>
</html>
{{ title }} 和 {{ name }} 是模板占位符,将在渲染时被替换成实际的值。
在视图函数中渲染模板: app.py 文件代码:
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def home():
return render_template('index.html', title='Welcome Page', name='John Doe')
if __name__ == '__main__':
app.run(debug=True)
render_template('index.html', title='Welcome Page', name='John Doe'):渲染 index.html 模板,并将 title 和 name 变量传递给模板。
2. 模板继承 模板继承允许你创建一个基础模板,然后在其他模板中继承和扩展这个基础模板,避免重复的 HTML 代码。 创建基础模板:在 templates 文件夹中创建一个基础模板 base.html。 templates/base.html 示例:
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}My Website{% endblock %}</title>
</head>
<body>
<header>
<h1>My Website</h1>
</header>
<main>
{% block content %}{% endblock %}
</main>
<footer>
<p>Footer content</p>
</footer>
</body>
</html>
{% block title %}{% endblock %} 和 {% block content %}{% endblock %} 是定义的可替换区域。
创建子模板:在 templates 文件夹中创建一个子模板 index.html,继承 base.html。 templates/index.html 文件代码:
{% extends "base.html" %}
{% block title %}Home Page{% endblock %}
{% block content %}
<h2>Welcome to the Home Page!</h2>
<p>Content goes here.</p>
{% endblock %}
{% extends "base.html" %}:继承基础模板。
{% block title %} 和 {% block content %}:重写基础模板中的块内容
3. 控制结构 Jinja2 提供了多种控制结构,用于在模板中实现条件逻辑和循环。 条件语句:
{% if user %}
<p>Welcome, {{ user }}!</p>
{% else %}
<p>Please log in.</p>
{% endif %}
{% if user %}:检查 user 变量是否存在,如果存在,则显示欢迎消息,否则显示登录提示。
循环语句:
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% for item in items %}:遍历 items 列表,并为每个项生成一个
4. 过滤器 过滤器用于在模板中格式化和处理变量数据。
<p>{{ name|capitalize }}</p>
<p>{{ price|round(2) }}</p>
{{ name|capitalize }}:将 name 变量的值首字母大写。 {{ price|round(2) }}:将 price 变量的值四舍五入到小数点后两位。
5. 宏和模板包含 宏是可重用的模板片段。模板包含允许你在一个模板中插入另一个模板的内容。
创建宏 templates/macros.html 代码文件:
{% macro render_item(item) %}
<div>
<h3>{{ item.title }}</h3>
<p>{{ item.description }}</p>
</div>
{% endmacro %}
使用宏: templates/index.html 文件代码:
{% from "macros.html" import render_item %}
<h1>Items</h1>
{% for item in items %}
{{ render_item(item) }}
{% endfor %}
{% from "macros.html" import render_item %}:导入宏。 {{ render_item(item) }}:调用宏来渲染每个 item。
6. 安全性 自动转义:Jinja2 默认会对模板中的变量进行自动转义,防止 XSS 攻击。
{{ user_input }}
{{ user_input }}:用户输入的内容会被自动转义,以避免恶意脚本的注入。7. 模板上下文 视图函数中传递的变量成为模板的上下文,这些变量可以在模板中直接使用。
@app.route('/profile/<username>')
def profile(username):
user = {'name': username, 'age': 25}
return render_template('profile.html', user=user)
templates/profile.html 文件代码:
<h1>{{ user.name }}</h1>
<p>Age: {{ user.age }}</p>
{{ user.name }} 和 {{ user.age }}:在模板中访问 user 变量的属性。
处理表单数据涉及到接收、验证和处理用户提交的表单。Flask 提供了基本的表单处理功能,但通常结合 Flask-WTF 扩展来简化表单操作和验证。
- 基本表单处理:使用 request.form 获取表单数据。
- 使用 Flask-WTF:结合 WTForms 进行表单处理和验证,简化表单操作。
- 表单验证:使用验证器确保表单数据的有效性。
- 文件上传:处理文件上传和保存文件。
- CSRF 保护:确保表单免受跨站请求伪造攻击。
创建 HTML 表单 templates/form.html 文件代码:
<!DOCTYPE html>
<html>
<head>
<title>Form Example</title>
</head>
<body>
<form action="proxy.php?url=https%3A%2F%2Fgithub.com.%2Fsubmit" method="post">
<label for="name">Name:</label>
<input type="text" id="name" name="name">
<br>
<label for="email">Email:</label>
<input type="email" id="email" name="email">
<br>
<input type="submit" value="Submit">
</form>
</body>
</html>
action="proxy.php?url=https%3A%2F%2Fgithub.com.%2Fsubmit":表单数据提交到 /submit 路径。 method="post":使用 POST 方法提交数据。
处理表单数据 app.py 文件代码:
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def form():
return render_template('form.html')
@app.route('/submit', methods=['POST'])
def submit():
name = request.form.get('name')
email = request.form.get('email')
return f'Name: {name}, Email: {email}'
if __name__ == '__main__':
app.run(debug=True)
request.form.get('name') 和 request.form.get('email'):获取提交的表单数据。