路由
路由
- 定义路由
- 路由变量
- 路由转换器
- 自定义转换器
1. 定义路由
定义路由的三个细节
- 路由对应的URL必须以 / 开头
- app.url_map 获取所有路由规则
路由规则中主要包含 URL资源段、支持的请求方式、视图函数标记 三部分内容 - app.route() 的 methods参数 指定路由支持的请求方式
from flask import Flask
app = Flask(__name__)
# 1.路由对应的URL必须以/开头
# 2.通过app的url_map属性获取所有的路由规则 (URL资源段 支持的请求方式 视图函数标记)
# 3.默认只有get,head ,可以通过route方法的methods参数指定路由支持的请求方式
@app.route('/hello', methods=['post', 'get'])
def index():
return "index"
if __name__ == '__main__':
print(app.url_map)
# 获取路由信息
# for rule in app.url_map.iter_rules():
# print(rule.rule, rule.methods, rule.endpoint)
app.run(debug=True)
路由变量
- 路由变量的作用是 传递URL路径参数, 实现动态URL
- 格式: /xx/<路由变量>
from flask import Flask
app = Flask(__name__)
# 路由变量: 传递URL路径参数
# 格式: /user/<路由变量名>
@app.route('/user/<userid>')
def index(userid): # 必须定义同名形参接收路由变量的值
print(userid)
return "index"
if __name__ == '__main__':
app.run(debug=True)
路由转换器
- 路由转换器的作用是 对URL传递的参数进行格式校验, 类似Django设置URL时的正则表达式参数
- 格式: /xx/<转换器名:路由变量>
- 所有的转换器类都继承自 BaseConverter 类
from flask import Flask
app = Flask(__name__)
# 路由转换器: 对路由变量进行格式校验 条件不满足返回404
# 格式: /user/<路由转换器名:路由变量>
@app.route('/user/<int:userid>') # int: 内置转换器, 要求1-n个整数
def index(userid):
print(userid)
return "index"
if __name__ == '__main__':
app.run(debug=True)
自定义转换器
- 除了使用内置的变量转换器, 开发者还可以自定义转换器, 更加灵活的校验路由变量
- 使用自定义转换器的步骤
定义转换器类, 继承BaseConverter
设置regex属性 (正则匹配规则)
应用添加自定义转换器
# 自定义转换器:
# 1.定义转换器类, 继承BaseConverter
# 2.设置regex属性 (正则匹配规则)
# 3.添加自定义转换器
from flask import Flask
from werkzeug.routing import BaseConverter
app = Flask(__name__)
# 1.定义转换器类
class MobileConverter(BaseConverter):
# 2.设置regex属性(匹配规则)
regex = '1[3-9]\d{9}$' # 不要设置开头的^
# 3.添加自定义转换器
app.url_map.converters['mob'] = MobileConverter
@app.route('/user/<mob:mobile>')
def index(mobile):
print(mobile)
return "index"
if __name__ == '__main__':
# 获取所有的转换器 {转换器名: 转换器类}
# print(app.url_map.converters)
app.run(debug=True)
请求
flask的请求数据通过 request 对象来获取
不像django视图中需要把request当参数,flask需要导入request
from flask import Flask, request
from werkzeug.datastructures import FileStorage
app = Flask(__name__)
@app.route('/', methods=['get', 'post'])
def index():
# 获取请求的基础数据
# print(request.url) # 请求的URL
# print(request.method) # 本次请求的请求方式
# print(request.headers) # 获取请求头信息 类字典对象
# print(request.headers['Host'])
# print(request.headers.get('Host')) # 建议使用get方法, 键不存在不报错
# 请求传递数据 1> URL路径 -> 路由变量 2> 查询字符串 get 3> 请求体 post 4> 请求头 -> request.headers
# 获取查询字符串 -> request.args xx?name=zs&age=20 类字典对象
# print(request.args.get('name'))
# print(request.args.get('age'))
# 请求体: 键值对(表单) 文本(json/xml) 文件(图片/音频)
# 获取post键值对 -> request.form 类字典对象
# print(request.form.get('username'))
# 获取post文本数据 -> request.data / request.json
# print(request.data) # 返回bytes类型
# print(request.json.get('age')) # request.json直接将json字符串转为字典
# 获取post文件 -> request.files 类字典对象
file = request.files.get("avatar") # type: FileStorage
# print(type(file)) # 返回 FileStorage文件对象
# 将文件保存到本地
file.save('123.jpg')
# 获取文件的二进制数据
# img_bytes = file.read()
# print(img_bytes)
return "index"
if __name__ == '__main__':
app.run(debug=True)
访问静态资源
将静态资源放入到 项目的 static 文件夹中
通过内置的静态资源的访问路由, URL路径格式为 /static/<filename>
如 static目录放入文件 123.jpg, 则访问URL为 http://127.0.0.1:5000/static/123.jpg
Flask对象的初始化参数 也可以 修改静态资源的存储和访问路径
from flask import Flask
app = Flask(__name__, # 导入名称, flask会根据该参数查询静态文件的存储路径
# 官方建议直接使用__name__, 表示从当前目录中查询静态文件存储路径
static_folder="static", # 设置静态文件的存储目录(默认)
static_url_path='/res/img', # 设置静态文件的URL访问路径 如 127.0.0.1:5000/res/img/123.jpg
)
if __name__ == '__main__':
app.run(debug=True)
设置响应数据
Flask中设置响应数据主要有两种方式
- 设置多个返回值
- 自定义响应对象
三个返回值
Flask中 视图函数的返回值可以设置三个, 分别对应 响应体, 响应状态码, 响应头
from flask import Flask, redirect, url_for
app = Flask(__name__)
@app.route('/demo1')
def demo1():
# 返回值: 响应体, 响应状态码, 响应头
return 'demo1', 400, {'A': 40}
if __name__ == '__main__':
app.run(debug=True)
自定义响应对象
视图函数返回的 str / bytes 类型数据会被包装为 Response 响应对象, 也可以 创建响应对象来 自定义响应头 等信息
from flask import Flask, make_response, Response
app = Flask(__name__)
# 自定义响应对象
@app.route('/demo2')
def demo2():
# 视图函数的返回值可以为str/bytes类型, 并且flask内部会将其包装为Response响应对象
# return 'hello flask'
# 创建响应对象 设置响应头时,需要手动创建响应对象
response = make_response('hello flask') # type: Response
# 设置响应头
response.headers['B'] = 10
return response
if __name__ == '__main__':
app.run(debug=True)
返回JSON
- 如果接口需要返回 JSON 数据,在 Flask 中可以直接使用 jsonify() 生成一个 JSON 的响应
- 不推荐使用 json.dumps() 直接返回,因为返回的数据要符合 HTTP 协议规范,如果是 JSON 需要指定 content-type:application/json
from flask import Flask, make_response, Response, jsonify
app = Flask(__name__)
@app.route('/demo3')
def demo3():
dict1 = {'name': 'zs', 'age': 20}
# 字典转json字符串
# return json.dumps(dict1)
# 可以将字典转json字符串, 并且设置响应头的content-type为application/json
return jsonify(dict1)
# return jsonify(name='zs', age=20) # 也支持关键字实参的形式
if __name__ == '__main__':
app.run(debug=True)
重定向
flask中通过 redirect() 实现重定向功能
from flask import Flask, redirect
app = Flask(__name__)
@app.route('/demo3')
def demo3():
return jsonify(name='zs', age=20)
@app.route('/demo4')
def demo4():
# 重定向到指定网站
# return redirect('http://www.baidu.com')
# 重定向到自己的路由 只需要URL资源段
return redirect('/demo3')
if __name__ == '__main__':
app.run(debug=True)
状态保持
1. Cookie
将数据保存在 客户端 (用户的电脑上), 可以减轻服务器压力
访问网站时, 浏览器会 自动 将该网站的cookie数据发送给服务器
保存一些 不太重要的数据
from flask import Flask, make_response, Response, request
app = Flask(__name__)
@app.route('/')
def index():
# 后端设置cookie: 通过响应体的set_cookie字段
# 创建响应对象
response = make_response('index') # type: Response
# 设置响应头的set_cookie字段 value必须是str/bytes类型
response.set_cookie('per_page', '10', max_age=86400)
# 删除cookie 本质: 设置max-age=0
# response.delete_cookie('per_page')
# 返回响应对象
return response
@app.route('/demo1')
def demo1():
# 获取cookie: 浏览器会自动通过请求头的cookie字段来传递cookie数据
# request.cookies 直接获取到字典形式的cookie数据
print(request.cookies.get('per_page'))
return 'demo1'
if __name__ == '__main__':
app.run(debug=True)
2. Session
将数据保存在 服务端 (服务器的数据库中), 安全性更高
保存一些 重要/敏感的数据
from datetime import timedelta
from flask import Flask, session
app = Flask(__name__)
# 设置应用秘钥 会被用于session签名
app.secret_key = 'test'
# 设置session过期时间 默认31天
app.permanent_session_lifetime = timedelta(days=7)
@app.route('/')
def index():
# session是一个类字典对象, 对其取值/赋值 就可以实现session数据的读写
# 记录session数据
session['username'] = 'zs'
# 设置session支持过期时间
session.permanent = True
# 删除session数据
# session.pop('username')
return "index"
@app.route('/demo1')
def demo1():
# 获取session数据
name = session.get('username')
print(name)
return 'demo1'
if __name__ == '__main__':
app.run(debug=True)
- flask的默认session机制 没有将session数据保存到服务器的数据库中, 而是将session数据编码后保存到了cookie中 (签名cookie机制)
- 可以使用 flask-session组件 来实现传统的session存储
- 注意:secret_key存在的意义是防止用户篡改session的(和jwt的秘钥类似)
- flask的session是通过secret_key加密之后存储到cookie里面的,键为session,值为session的加密值
- 该cookie通过字符串的分割之后,分成了三部分:内容序列化+时间+防篡改值
异常处理
flask对 HTTP错误 进行了封装, 可以捕获http错误, 也可以主动抛出http错误
from flask import Flask, abort
# flask对http错误进行了封装, 可以捕获http错误也可以主动抛出http错误
app = Flask(__name__)
# 捕获http错误
@app.errorhandler(404)
def error_404(error): # 一旦进行捕获, 要求必须定义形参接收具体错误信息
return "<h3>您访问的页面去浪迹天涯了</h3> %s" % error
# errorhandler不仅可以捕获http错误,还可以捕获系统内置错误
@app.errorhandler(ZeroDivisionError)
def error_zero(error):
return '除数不能为0'
@app.route('/')
def index():
# a = 1 / 0
abort(500) # 主动抛出异常 (只能抛出http错误)
return "index"
if __name__ == '__main__':
app.run(debug=True)
一旦在运行过程中报了404的错误,这里的装饰器就会捕捉到,并显示相应的错误信息,也可自定义错误信息