目录
Flask框架基本概述
Flask作为一个微框架,强调简单性和灵活性。它依赖于两个重要的python库来提供核心功能:
一、Werkzeug(Flask底层核心)
- WSGI工具集
- 本质是Socket服务端,处理HTTP请求预处理和响应生成
- 提供Request/Response对象封装、URL路由、Cookie管理等基础功能
- 采用线程隔离的LocalStack实现多请求并发处理
- 核心模块
- Routing模块:通过Rule类定义URL模式,MapAdapter执行匹配
- Request工具集:解析form/json数据、文件上传等HTTP请求数据
- Response工具集:设置响应头、状态码等
二、Jinja2(模板引擎)
- 核心特性
- 支持模板继承、控制结构(if/for)、过滤器等动态渲染逻辑
- 自动HTML转义防止XSS攻击
- 与Flask深度集成,通过render_template()调用
- 模板语法示例
{% extends "base.html" %}
{% block content %}
<h1>{{ title }}</h1>
{% for item in items %}
<div class="item">{{ item|capitalize }}</div>
{% endfor %}
{% endblock %}
三、两者协作关系
- 工作流程
- Werkzeug接收请求 → Flask处理逻辑 → Jinja2渲染模板 → Werkzeug返回响应
- 性能优化
- 模板编译缓存机制(Jinja2)
- 请求上下文局部变量(Werkzeug)
两者共同构成Flask的"微框架"特性基础,使开发者可灵活扩展其他功能
基本部署
安装flask
pip install flask
创建应用
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def home():
return 'Hello,World!'
if __name__ == '__main__':
app.run(debug=True)
代码解析:
- Flask(_name ):创建 Flask 应用实例,_name 参数用于 Flask 了解当前模块的名称,通常我们使用这个参数来帮助 Flask 在不同模块间进行配置。
- @app.route('/'):定义路由和视图函数的映射。'/"是根路径,当用户访问根 URL 时,Flask会调用 hello world()函数。
- return'Hello,world!':视图函数返回一个简单的字符串响应,Flask 会将其作为 HTTP 响应返回给客户端。
- app.run(debug=True):启动 Flask 开发服务器,debug=True 表示启用调试模式,这样可以在开发过程中自动重载应用,并在发生错误时显示详细信息。
运行应用
python3 home.py
Flask路由与视图函数
路由
一、核心概念解析
- 路由(Route)
- 本质:URL到Python函数的映射规则
- 作用:定义Web应用的访问入口,决定哪个URL触发哪个处理函数
- 特性:
• 支持静态路径(如/about
)和动态路径(如/user/<username>
)
• 可通过装饰器@app.route()
快速注册
典型部署
- 基础路由配置
from flask import Flask
app = Flask(__name__)
# 静态路由
@app.route('/')
def home():
return 'Welcome to Homepage'
# 动态路由
@app.route('/user/<username>')
def show_user(username):
return f'User: {username}'
if __name__ == '__main__':
app.run(debug=True)
此示例展示静态路由和带参数的动态路由实现
- 高级路由特性
flask import Flask, request
app = Flask(__name__)
# 类型转换器
@app.route('/post/<int:post_id>')
def show_post(post_id):
return f'Post ID: {post_id} (type: {type(post_id)})'
# 支持多种HTTP方法
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return 'Processing login'
return 'Show login form'
演示了参数类型转换和HTTP方法限制
使用Jinja2模块渲染HTML
Flask 结合 Jinja2 模板引擎来动态生成 HTML 页面。你可以将 HTML 文件与 Python 代码分离,保持应用结构清晰。在 Flask 中,模板文件默认存放在 templates 文件夹中。
假设我们有一个名为 greet.html 的模板文件,内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Flask Example</title>
</head>
<body>
<h1>Hello,{{ name }}!</h1>
</body>
</html>
我们可以通过render_template函数模块并传递动态数据:
from flask import render_template
@app.route('/greet/<name>')
def greet(name):
return render_template('greet.html',name=name)
return render_template('greet.html',name=name):Flask会加载greet.html模块,并将name的值传递给模块。模块中的{{ name }}会被替换为传入的值。
模块继承与块
Flask支持模板继承和块(Block)功能,这对于构建复杂页面非常有用。你可以在基础模板中定义通用的布局结构,在子模版中覆盖特定的部分。
基础模板 base.htm1:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset."UTF-8">
<title>(% block title %}My Website{% endblock %}</title>
</head>
<body>
<header>
<h1>Welcome to My website</h1>
</header>
<div>
{% block content %}{% endblock %}
</div>
<footer>
<p>© 2025 My Website</p>
</footer>
</body>
</html>
子模版index.html
{% extends 'base.html' %}
{% block title x}Home{% endblock %}
{% block content %}
<h2>Welcome to the homepage!</h2>
{% endblock %}
代码解析:
- {% extends'base,html’%}:子模板继承了 base.html 模板,
- {% block title %}Home{% endblock %}:覆盖父模板中的 title 块。
- {% block content %}:定义页面的主要内容区域。
Flask表单处理与用户输出
1. 基础表单处理(原生 Flask)
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
return f"登录成功: 用户名 {username}"
return render_template('login.html')
代码解析:
request.method
判断请求类型,GET 返回表单页面,POST 处理提交数据。request.form
直接获取表单数据,需确保字段名与 HTML 表单一致。- 未使用扩展库,适合简单场景,但缺乏自动验证和 CSRF 防护。
2. 使用 Flask-WTF 扩展
flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Length
class LoginForm(FlaskForm):
username = StringField('用户名', validators=[DataRequired(), Length(min=4)])
password = PasswordField('密码', validators=[DataRequired()])
submit = SubmitField('登录')
代码解析:
- 继承
FlaskForm
定义表单字段,每个字段绑定验证器(如DataRequired
必填)。 StringField
和PasswordField
分别对应文本和密码输入框。
from flask import Flask, render_template
from forms import LoginForm
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key' # CSRF防护必需
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit(): # 自动验证表单
return f"欢迎, {form.username.data}"
return render_template('login_wtf.html', form=form)
validate_on_submit()
自动检查请求类型和字段验证。SECRET_KEY
启用 CSRF 防护,防止跨站攻击。- 通过
form.field_name.data
获取已验证的数据。
3. 模板文件示例
<!DOCTYPE html>
<html>
<head>
<title>登录</title>
</head>
<body>
<form method="POST">
{{ form.hidden_tag() }} <!-- 渲染CSRF令牌 -->
{{ form.username.label }} {{ form.username() }}
{{ form.password.label }} {{ form.password() }}
{{ form.submit() }}
</form>
</body>
</html>
代码解析:
form.hidden_tag()
自动生成 CSRF 令牌隐藏字段。form.field_name()
渲染表单字段,form.field_name.label
渲染标签。
4. 文件上传处理
from flask import Flask, request
from werkzeug.utils import secure_filename
app = Flask(__name__)
@app.route('/upload', methods=['POST'])
def upload_file():
file = request.files['file']
filename = secure_filename(file.filename)
file.save(f"uploads/{filename}")
return "文件上传成功"
代码解析:
request.files
获取上传文件对象。secure_filename
过滤危险字符,防止路径遍历攻击。
关键点总结
- 原生表单:简单但功能有限,需手动处理验证和安全。
- Flask-WTF:推荐使用,集成验证、CSRF 和模板渲染。
- 文件上传:需注意安全处理和存储路径。
Flask的项目结构与部署
项目结构
随着应用的复杂度增加,Flask应用的结构通常会发生变化。典型的Flask项目结构如下:
/my_flask_app
/app
/templates
index.html
/static
/css
/js
__init__.py
routes.py
forms.py
run.py
- /templates:存放所有HTML模板文件
- /static:存放静态文件(如CSS、JS、图片等);
- __init__.py:初始化Flask应用;
- routes.py:定义所有路由和视图函数;
- forms.py:定义表单类;
部署Flask应用
应用的开发环境通常使用Flask run启动,但在生产环境中,我们需要通过更强大的web服务器进行部署,常有的有:
- Gunicorn:一个Python WSGI HTTP服务器,常用于生产环境部署。
- Nginx:作为反向代理,前端处理静态文件请求,转发动态请求到Flask应用。
部署时,可以通过以下命令启动Flask应用:
gunicorn -w 4 run:app