二、Flask_路由定义与http的请求/响应
1. 路由定义
1.1 路由基本定义
... # 指定访问路径为 demo @app.route('/demo') def demo(): return 'demo' ...
1.2 路由传递参数(两种)
- 没有限定类型
# @app.route('/user/<user_id>') def user_info(user_id): return 'hello %s' % user_id
- 限定数据类型
# @app.route('/user/<int:user_id>') def user_info(user_id): return 'hello %d' % user_id
1.3 路由限定请求方式
# @app.route('/demo', methods=['GET', 'POST']) def demo(): # 直接从请求中取到请求方式并返回 return request.method
1.4 正则匹配路由
在 web 开发中,可能会出现限制用户访问规则的场景,那么这个时候就需要用到正则匹配,根据自己的规则去限定请求参数再进行访问
-
导入转换器基类:在 Flask 中,所有的路由的匹配规则都是使用转换器对象进行记录
-
自定义转换器:自定义类继承于转换器基类
-
添加转换器到默认的转换器字典中
-
使用自定义转换器实现自定义匹配规则
代码实现
- 导入转换器基类
from werkzeug.routing import BaseConverter
- 自定义转换器
# 自定义正则转换器 from werkzeug.routing import BaseConverter class RegexConverter(BaseConverter): def __init__(self,url_map,*args): super(RegexConverter, self).__init__(url_map) # 正则参数 self.regex = args[0]
- 添加转换器到默认的转换器字典中,并指定转换器使用时名字为: re
# 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: re app.url_map.converters['re'] = RegexConverter
- 使用转换器去实现自定义匹配规则
# 当前此处定义的规则是:手机号码 # 正则匹配路由 @app.route("/login/<re('1\d{10}'):mobile>") def login(mobile): return mobile
1.5 系统自动转换器
# DEFAULT_CONVERTERS = { 'default': UnicodeConverter, 'path': PathConverter, 'string': UnicodeConverter, 'any': AnyConverter, 'int': IntegerConverter, 'float': FloatConverter, 'uuid': UUIDConverter, }
系统自带的转换器具体使用方式在每种转换器的注释代码中有写,请留意每种转换器初始化的参数。
2 http请求与响应
2.1 请求
-
-
作用:在视图函数中取出本次请求数据
-
导入:from flask import request
获取方法
request.属性
常用的属性如下:
属性 | 说明 | 类型 |
---|---|---|
data | 记录请求的数据,并转换为字符串 | * |
form | 记录请求中的表单数据 | MultiDict |
args | 记录请求中的查询参数 | MultiDict |
cookies | 记录请求中的cookie信息 | Dict |
headers | 记录请求中的请求头 | EnvironHeaders |
method | 记录请求使用的HTTP方法 | GET/POST |
url | 记录请求的URL地址 | string |
files | 记录请求上传的文件 | * |
json | 记录请求的json数据 |
属性下有属性
使用方法 request.args.属性(参数)
属性 | 说明 | 类型 | 举例 |
get() | 获取一个参数的一个值 | request.args.get("username") | |
getlist() | 获取一个参数的多个值 | List | request.args.getlist("love") |
to_dict( ) | 把传递过来的数据抓换成原生的字典 | Dict | request.args.to_dict() |
to_list( ) | request.headers.to_list() |
from flask import Flask # 新增一个配置文件,在配置文件中设置配置信息 from config import Config from flask import request # from collections import OrderedDict # 有序字典 app = Flask(__name__) # 调用app.config加载配置 app.config.from_object(Config) from werkzeug.routing import BaseConverter class RegexConverter(BaseConverter): def __init__(self,url_map,*args): super(RegexConverter, self).__init__(url_map) # 正则参数 self.regex = args[0] # converter["路由转换器名称"] = 实现路由转换功能的自定义类 app.url_map.converters['re'] = RegexConverter # 绑定路由 @app.route("/") def index(): return "hello flask" # 默认情况下,路由使用的就是关键字参数,也叫"命名路由" # router(路由地址, http请求方式 ) @app.route("/list/<int:page>/<string:content>",methods=["GET","POST"]) def mylist(content,page): return "第%s页<br>内容:%s" % (page,content) # 正则匹配路由 @app.route("/login/<re('1\d{10}'):mobile>") def login(mobile): return mobile """获取客户端的请求""" @app.route("/request") def req1(): """获取查询字符串""" query_string = request.args # print(query_string) """打印效果: ImmutableMultiDict([('username', 'xiaoming'), ('user_id', '1')])""" # 获取一个参数的一个值 username = request.args.get("username") # print(username) """打印效果: xiaoming""" # 获取一个参数的多个值 # http://www.luffycity.cn:5000/request?username=xiaoming&user_id=1&love=吹牛&love=睡觉 love = request.args.getlist("love") # print(love) """打印效果: ['吹牛', '睡觉']""" # 把传递过来的数据抓换成原生的字典 data = request.args.to_dict() # print(data) """打印效果: {'username': 'xiaoming', 'user_id': '1', 'love': '吹牛'} """ return "ok" @app.route("/request2",methods=["POST"]) def req2(): """获取post数据和请求头""" # print( request.data ) # """打印结果: # b'{\n\t"username":"xiaoming",\n\t"age":18,\n\t"sex":1\n}' # """ # # import json # from flask import json # data = json.loads(request.data) # print(data) # """打印结果: # {'username': 'xiaoming', 'age': 18, 'sex': 1} # # """ # # """获取请求行数据""" # print( request.headers ) # print( request.headers.to_list() ) """获取上传文件""" print( request.files ) print( request.files.get("avatar") ) """打印效果: ImmutableMultiDict([('avatar', <FileStorage: 'avatar.png' ('image/png')>)]) <FileStorage: 'avatar.png' ('image/png')> """ return "ok" if __name__ == '__main__': app.run()
2.2 响应
flask默认支持2种响应方式:
- 页面响应: 重定向(url_for)
响应的时候,flask也支持自定义http响应状态码
2.2.1 数据响应
响应html文本
@app.route("/") def index(): # [默认支持]响应html文本 return "<img src='http://flask.pocoo.org/static/logo.png'>"
返回json格式
from flask import Flask, request, jsonify @app.route("/") def index(): # 也可以响应json格式代码 data = [ {"id":1,"username":"liulaoshi","age":18}, {"id":2,"username":"liulaoshi","age":17}, {"id":3,"username":"liulaoshi","age":16}, {"id":4,"username":"liulaoshi","age":15}, ] return jsonify(data)
2.2.2 重定向
重定向到外部网站
# 页面跳转响应 @app.route("/user") def user(): # 页面跳转 redirect函数就是response对象的页面跳转的封装 # Location: http://www.baidu.com return redirect("http://www.baidu.com")
重定向到视图函数
-
from flask import redirect,url_for @app.route('/user/<user_id>') def user_info(user_id): return 'hello %d' % user_id @app.route("/index") def index(): # 1. 跳转到站内地址,例如其他页面 return redirect("/response") # 2.1 跳转到站内视图函数对应的页面中[没有附带地址参数] return redirect(url_for("index")) # 2.2 跳转到站内视图函数对应的页面中[有附带地址参数,通过命名参数传递路由参数] return redirect(url_for('user_info', user_id=100))
2.2.3 自定义状态码
在 Flask 中,可以很方便的返回自定义状态码,以实现不符合 http 协议的状态码,例如:status code: 666
@app.route('/demo') def demo(): return '状态码为 666', 400