THE ULTIMATE GUIDE TO FLASK WEB FRAMEWORK
作者:禅与计算机程序设计艺术
1.简介
什么是Flask?
Flask 是一种以 Python 为基础语言设计的高效轻量级 Web 应用框架。 Flask 通过其直观易用的设计和强大的功能特性,能够显著提升开发人员编写 Web 应用的效率。 Flask 提供丰富的内置功能模块包括但不限于静态路由管理模块动态模板引擎模块数据库交互接口以及身份认证组件等。
为什么要使用Flask?
- 轻量级:Flask被公认为是最轻量级的Web框架之一。相比于Django或Tornado等主流框架,在性能方面表现更为突出。对于小型项目而言,这是一个非常合适的选择。
- 易上手:Flask以其直观的设计著称,在学习成本方面非常低效。由于其采用WSGI协议(Web服务器网关接口),因此在部署和调试过程中也更加便捷。
- 模块化:基于标准接口实现模块间的互联互通是Flask的核心设计理念之一。例如,Flask-SQLAlchemy作为一个常用扩展库,在此基础上提供了对象关系映射(ORM)功能。
- 拓展性强:拥有良好的可扩展性是Flask的一大特点,在GitHub上已有多达数百个第三方扩展库可供使用。其中如 Flask-Login 扩展库则实现了用户登录功能的支持。
- 支持RESTful API:基于RESTful架构设计的 Flask 内置了完整的RESTful API支持功能。
- 文档齐全:官方提供了详尽的技术文档和实践示例资源库,并且开发者能够迅速熟悉并掌握其使用方法。
如何安装Flask?
可以用pip命令直接安装Flask。安装过程如下:
pip install flask
代码解读
安装成功后,可以使用import语句导入Flask模块。
from flask import Flask
app = Flask(__name__)
代码解读
上面的代码生成一个Flask实例,并将其赋值给变量app。通过指定__name__参数来确定当前脚本文件名;当需要时,则有助于查找资源文件。
使用Flask开发web服务
定义路由映射
在Flask框架中,路由指的是客户端向其web应用发送的URL地址。每当用户向其web应用发送该URL时,Flask会被配置系统识别并调用相应的视图函数以处理请求。例如,在访问/hello资源时,默认会触发hello()功能以响应这一请求操作。以下段落将展示如何设置一个最简单的默认路由配置示例
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello World!'
代码解读
这段代码为根目录设置了特定的路由配置。
当用户登录至http://localhost:5000/时, index()函数将输出字符串'Hello World!'
路由参数
有时需要动态获取应用中的路由参数,在进行网络请求时可以通过URL中的ID字段快速定位到目标用户数据。 Flask框架支持使用装饰器将所需路径参数传递至路由映射函数中,并在请求处理时自动提取这些路径变量值。以下实例演示了如何配置带有路径变量的URL模式
from flask import Flask
app = Flask(__name__)
@app.route('/user/<int:id>')
def user_profile(id):
user = query_db('SELECT * FROM users WHERE id=%d', [id])
if not user:
abort(404)
else:
return render_template('user_profile.html', user=user)
代码解读
在上述代码中,默认配置了处理访问日志的路由规则。其中间变量int:id被识别为整型数据类型。当客户端发送请求至端点地址/user/1时,在服务器端会将该数值作为int类型参数传递给处理逻辑函数user_profile().比如我们可以通过数据库存储机制记录每位用户的登录信息,并在后续操作中检索这些数据用于分析用户的活动情况.
返回静态文件
Flask框架支持快速返回静态资源,并非仅限于图片文件这一类资源。当你运行Flask应用时,在其开发环境中你可以将这些静态资源放置在一个特定目录中,并通过配置路由映射实现快速访问。以下实例阐述了配置路由以实现快速访问资源的方法。
from flask import Flask, send_from_directory
app = Flask(__name__)
@app.route('/img/<path:filename>')
def get_image(filename):
return send_from_directory('static/images/', filename)
代码解读
请求上下文
在Flask框架中,每一次HTTP请求都会与一个Request对象相关联,并且该对象的生命周期仅持续一次。然而,在整个Flask应用的生命周期内始终可用。因此,在请求发生时我们可以对其实施相应的处理。每一个Request对象都附有一个上下文指针g。每个视图函数都可以读取或修改该变量g以实现不同视图之间的通信。以下实例演示了如何通过视图函数访问并修改g变量。
from flask import Flask
app = Flask(__name__)
@app.before_request
def before_request():
g.counter = getattr(g, 'counter', 0) + 1
@app.route('/')
def index():
count = str(getattr(g, 'counter', '?'))
return '<p>This page has been viewed {} times.</p>'.format(count)
代码解读
在每个请求处理之前,上述代码会调用before_request()函数。该函数会检查g变量中的counter属性是否存在;如果没有,则将counter值初始化为0;如果有,则会将counter值加1。随后,在index()函数中会读取该counter值,并生成显示页面所需的HTML代码。
模板渲染
在Flask框架中,默认配置已经集成了一个高效的模板引擎。常见的包括Jinja2和Mako等工具。此外,默认情况下Flask框架还会自动生成一个基于Jinja2的模板引擎。因此无需额外配置即可直接应用。通过示例代码可以清晰地看到如何将这些工具应用于实际项目中。
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def hello_world():
name = 'John Doe'
return render_template('hello.html', name=name)
代码解读
此代码实现了某种功能。其中包含了关键参数name,并返回一个包含该参数的HTML页面。随后,在templates目录中生成了一个名为hello.html的模板文件。内容如下:
<h1>Hello {{ name }}!</h1>
代码解读
当用户访问HTTP服务器地址http://localhost:5000时,在Flask框架中会自动加载并解析指定模板文件中的模板变量{{ name }}的内容。
HTTP请求
Flask能够处理HTTP协议的各种请求方法,具体包括GET、POST、PUT和DELETE等。以下将详细说明如何针对不同类型的HTTP请求方法进行处理。
from flask import Flask, request
app = Flask(__name__)
@app.route('/', methods=['GET'])
def home():
return 'Home Page'
@app.route('/login', methods=['POST'])
def login():
form = request.form
username = form['username']
password = form['password']
if authenticate(username, password):
return redirect(url_for('success'))
else:
flash('Invalid credentials')
return redirect(url_for('home'))
@app.route('/success')
def success():
return 'Logged in successfully'
代码解读
上面代码定义了三个视图函数,分别处理GET请求、POST请求和GET请求。
- HTTP GET方法将返回指定的字符串'Home Page'。
- 当用户提交POST请求至'/login'路径时, 服务器将接收来自客户端的表单数据并执行身份验证操作. 如果验证成功, 则跳转至'success()'页面; 如果失败, 则显示错误信息并跳转回主页面.
- HTTP GET方法至'/success'路径将返回'Logged in successfully'的信息.
文件上传
Flask具备文件上传功能,并且能够将用户的上传文件保存至本地硬盘。以下案例演示了如何处理上传的文件。
from flask import Flask, request, redirect, url_for, jsonify
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('./uploads/{}'.format(f.filename))
return redirect(url_for('uploaded_file',
filename=f.filename))
return '''
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form method=post enctype=multipart/form-data>
<input type=file name=the_file>
<br><br>
<input type=submit value=Upload>
</form>
'''
@app.route('/uploads/')
def uploaded_file(filename):
return send_from_directory('uploads',
filename)
代码解读
上面代码声明了一个用于上载文件的视图函数,并实现了该功能的同时将上传至./uploads目录下的机制。此外还声明了另一个浏览已上传文件并返回其内容的功能模块。
消息闪现(Flash)
在Flask应用开发中常见需求包括向用户提供通知信息而不持久化存储这些消息。该框架提供了一种名为Flash的技术来实现这一目标。Flash的工作流程如下:首次执行Flash动作会将消息暂存在Session变量中;而当再次执行Flash动作时系统会从Session变量中读取之前保存的消息并展示给用户。以下示例展示了如何集成Flash功能到应用中。
from flask import Flask, flash, redirect, session, url_for
app = Flask(__name__)
@app.route('/')
def index():
flash("You have logged out")
return redirect(url_for('login'))
@app.route('/login')
def login():
error = None
if 'logged_in' in session:
error = "You are already logged in"
return '''
% if error is not None:
<div class="error">{{ error }}</div>
% end
<form action="" method="post">
<p><input type=text name=username>
<p><input type=password name=password>
<p><button type=submit>Login</button>
</form>
'''
@app.route('/login', methods=['POST'])
def do_login():
if valid_login(request.form['username'],
request.form['password']):
session['logged_in'] = True
flash("You were logged in")
return redirect(url_for('index'))
else:
flash("Invalid login or password")
return redirect(url_for('login'))
代码解读
代码定义了一个包含三个视图功能模块的应用程序:index模块负责登出操作;login模块则用于展示并管理登录界面;do_login模块则负责处理用户的登录请求数据。具体而言,在首次使用时如果没有已初始化的session记录,则会展示登录表单供用户填写;一旦完成了表单填写并调用了验证逻辑后,则会根据验证结果决定是否将logged_in标记存入session中并显示相应的提示信息。此外,在整个生命周期中每当调用一次flash()方法时都会清除当前消息记录以确保界面信息的及时更新。
状态保持
在Flask应用框架中,我们能够借助 sessions 来完成状态保存的任务。借助 session 对象我们能够将一些重要数据保留在客户端浏览器上,并且使得后续的所有请求都能够直接访问这些存储的数据。例如,在下面的内容中我们将详细展示这一过程的具体实现步骤。
from flask import Flask, session
app = Flask(__name__)
@app.route('/')
def index():
if 'visits' in session:
session['visits'] += 1
else:
session['visits'] = 1
return 'Number of visits: {}'.format(session['visits'])
代码解读
上述代码实现了某个视图函数的功能,在处理网络请求时能够有效记录用户的访问频率信息。当用户首次访问网站时,在服务器端会调用Flask框架来管理会话数据。系统会首先查看session中是否存在名为'visits'的属性。如果存在,则将'visits'的值加一;反之,则将'visits'初始化为一。返回的结果字段记录了当前用户的访问频率信息。
用户认证
开发人员在实际应用开发中常需实现用户认证功能。采用Flask框架并结合flask/login扩展库能够有效地完成这一功能需求。通过flask/login扩展库实现了用户的身份验证功能,在此过程中开发者无需直接处理session和cookie管理等问题即可轻松完成基本的安全验证措施。例如,在下面的部分我们将详细阐述如何利用该模块完成用户的认证流程。
from flask import Flask, render_template, request, \
redirect, url_for, flash, session,\
current_app
from flask_login import LoginManager, UserMixin, \
login_required, login_user, logout_user
app = Flask(__name__)
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
@login_manager.user_loader
def load_user(user_id):
return User.get(user_id)
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
user = User.get_by_auth(username, password)
if user:
login_user(user)
return redirect(url_for('protected'))
else:
flash('Invalid username or password.')
return redirect(url_for('login'))
else:
return render_template('login.html')
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('index'))
@app.route('/protected')
@login_required
def protected():
return 'Logged in as: {} | '.format(current_user.username)\
+ '<a href="/logout">Logout</a>'
if __name__ == '__main__':
db = connect_to_database()
create_tables(db)
...
app.run()
代码解读
该系统实现了基础的用户认证功能。随后,我们定义了一个User类,并在此类中包含了若干与账户相关的功能模块。例如,在该框架中提供了通过用户名和密码验证获取用户信息的方法;之后又注册了一个login_manager对象,并对该对象进行了配置以确保其能够处理指定路径上的登录页面请求;而load_user()方法则用于在成功登录后获取当前用户的详细信息;处理完完整的身份验证流程后又实现了两个核心功能:一个是login()函数用于处理用户的登录请求;另一个是针对需要权限控制的操作提供了Protected()标记;最后又为退出操作设置了相应的条件即logout()函数必须在其参数配置中包含@livesession=True才能被触发
RESTful API
在开发实际的Web应用时,常见于其中开发者们会频繁地需求支持RESTful API的功能。Flask这个框架内置了一个专门提供RESTfulAPI功能的模块,在仅需编写几行高效而简洁代码的情况下即可实现实例化创建API服务功能。以下实例演示了如何构建一个RESTfulAPI框架结构
from flask import Flask, jsonify, make_response
app = Flask(__name__)
products = [{'id': 1, 'name': 'iPhone'},
{'id': 2, 'name': 'iPad'}]
@app.route('/products/')
def get_all_products():
response = {
'status':'success',
'data': products
}
return jsonify(response), 200
@app.route('/products/<int:product_id>/')
def get_one_product(product_id):
product = next((item for item in products if item["id"]==product_id), None)
if product:
response = {
'status':'success',
'data': product
}
return jsonify(response), 200
else:
response = {
'status': 'fail',
'message': 'Product not found.'
}
return jsonify(response), 404
@app.errorhandler(404)
def not_found(error):
response = {
'status': 'fail',
'message': 'Resource not found.'
}
return make_response(jsonify(response)), 404
if __name__ == '__main__':
app.run()
代码解读
该代码实现了基于API的产品管理功能包。此代码支持通过两个URL实现两种基本操作:获取全部商品和查看单一商品信息。该功能模块包括两部分核心逻辑:首先由get_all_products()函数负责生成完整的商品列表JSON数据;其次由get_one_product()功能则能够通过给定的产品ID生成相应的商品详情。此外,我们设计了自定义的not_found()功能模块,在资源不存在时会发送专门定制化的错误响应信息以提高系统的容错能力。最后,在整个开发过程中为了实现Flask框架的应用需求我们特别配置了启动与停止服务的相关接口以确保系统的稳定性和可维护性。
