3. Flask路由¶
准备工作:
- 新建文件夹
v2
- 文件夹下直接创建py程序
router_demo.py
- 把上面案例的代码复制粘贴过来,运行成功
路由可以理解成服务器的接待员,你远程访问服务器,接待员就会问你找谁干什么, 然后接待员会根据你的意图给你介绍相应的处理你事情的办事人员,我们一直强调 路由就是看门大爷,主要工作就是终极三问后给你顺便指个路。
3.1. 路由装饰器¶
django的路由需要单独的路由文件指定,flask相对简单,直接使用路由装饰器, 需要啥路由直接写在处理函数上面,so easy ~~~
# flask路由使用这种写法,跟django不太一样
@app.route('/')
def hw():
return "Hello 北京图灵学院"
以上代码的意思是,把对路由/
的访问用函数hw()
来处理。
路由最基本的参数是一个str类型URL。
3.2. 转换器-路由带参数¶
路由肯定会出现带参数的情况,我们大flask肯定也能easy处理掉的。
# 路由可以带转换器,用来表示参数
# stu_info可以直接使用整型参数stu_id, 此处转换器把传入的stu_id转换成int
@app.route('/stu/<int:stu_id>')
def stu_info(stu_id):
return "Hello {} 学生,你好".format(stu_id)
访问上面的URL后,得到的结果如下:
通过代码我们发现,我们输入的参数直接转换成参数对应的值,而且,参数的类型 其实是int的,虽然代码反应看不出来。
3.2.1. 转换器基本使用¶
这种能直接把传入的内容转换成别的类型并作为参数传入的代码叫转换器。
转换器的用法就是在路由定义中使用<converter:variable_name>
, 然后在处理函数中
就会多一个参数,参数名称为variable_name
,如上面代码所示。
Flask一共提供了以下几个默认转换器, 以下是源码werkzeug.routing
中的代码片段:
#: the default converter mapping for the map.
DEFAULT_CONVERTERS = {
"default": UnicodeConverter,
"string": UnicodeConverter, # 接受任何不包含斜杠的文本, 默认值
"any": AnyConverter, # 输入的值是一个可选项, 用法参见后面案例
"path": PathConverter, # 类似 string ,但可以包含斜杠
"int": IntegerConverter,
"float": FloatConverter,
"uuid": UUIDConverter, # UUID字符串
}
下面一个转换器例子如下:
# 多个转换器
@app.route('/me/<string:name>/<int:age1>/<int:age2>')
def me(name, age1, age2):
return "我是王晓静的同学{}, 遇见王晓静的时候我{}岁,今年我{}岁,请问我遇见她{}年了".\
format(name, age1, age2, age2-age1)
执行结果如下:
any转换器是规定几个可选项,如果在可选项里面,则运行路由通过,否则报错。
下面代码规定我传入的颜色只能是red, blue或者green, 否则报错:
@app.route('/colors/<any(red,blue,green):color>')
def my_color(color):
return "I like {}".format(color)
结果如下所示:
如果传入了别的颜色,则报错:
3.2.2. 自定义转换器¶
默认转换器不能满足需求,可以自定义自己的转换器,所有自定义转换器要求是
werkzeug.routing.BaseConverter
的子类。
# 自定义Converter
class TuLingConverter(BaseConverter):
regex = 'TuLing[0-9]{5}'
# 需要注册后才能用
app.url_map.converters['TL'] = TuLingConverter
@app.route('/conv/<TL:name>')
def stu(name):
return "My name is {}".format(name)
访问结果如下:
定义转换器很简单,我们看下转换器的源代码:
# wergzeug.routing.BaseConvert 源代码
class BaseConverter(object):
"""Base class for all converters."""
# 用来匹配的正则
regex = "[^/]+"
weight = 100
def __init__(self, map):
self.map = map
def to_python(self, value):
return value
def to_url(self, value):
if isinstance(value, (bytes, bytearray)):
return _fast_url_quote(value)
return _fast_url_quote(text_type(value).encode(self.map.charset))
- 其中最重要的是变量
regex
, 我们识别需要转换的内容需要用这个正则来识别 to_python
: 需要把URL转换成视图需要的值的时候调用to_url
: 当url_for
被执行,需要把一些值拼接出URL的时候调用
请参看Django的转换器
一个常见的案例是,让转换器可以自动按照我们定义的正则表达式来进行匹配,其实这个实现 起来很简单,直接把正则作为字符串传入即可:
##############################
# 自定义正则转换器
class RegexConverter(BaseConverter):
def __init__(self, url_map, *args):
super(RegexConverter, self).__init__(url_map)
# 将接受的第1个参数当作匹配规则, 简单直接
self.regex = args[0]
# 添加到映射关系中, 自定义的转换器起名叫 my_re
app.url_map.converters['my_re'] = RegexConverter
# 直接使用正则来把以 "TuLing"开头的跟着五个数字的字符串当做user_name进行处理
@app.route('/user/<my_re("TuLing\d{5}"):user_name>')
def user_info(user_name):
return "通过自动转换的用户名为: {}".format(user_name)
上述代码,只有在输入http://127.0.0.1:5000/user/TuLing12345
或者其他符合正则定义的
url时才会正确显示。
3.3. 指定请求方式¶
定义路由可以定义请求方法,通过限制请求方法,可以把不合理的请求拒绝。
在Flask中默认的请求方式为
- GET
- OPTION
- HEAD
如果想指定其他的请求方式,需要自己用methods关键字定义:
from flask import request
... ...
@app.route("/methode", methods=['GET', 'POST'])
def meth():
return "Http Request Methode: {}".format(request.method)
上面代码指定接收GET和POST访问。
为了测试POST,我们可以使用postman或者postwoman作为访问工具。
本教程采用postman,建议尝试postwoman,各方面比较据说都好,至少本人懒得搭建了, postman有现成的。
采用POST方法发送后结果如下:
如果使用除了GET和POST别的方法访问,会出现如下结果:
3.4. Werkzeug¶
Flask是基于Werkzeug的一个python框架,本节简单介绍下werkzeug
- Werkzeug是工具的意思,是一个遵循WSGI协议的python函数库
- WSGI(PythonWebServerGatewayInterface):
- Web服务器网关接口
- 是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。
- 自从WSGI被开发出来以后,许多其它语言中也出现了类似接口。
- 是一个规范,不是代码,是说明代码应该怎么写的指导书
- Werkzeug是WSGI的一个具体实现,是按照WSGI写的一套工具
- Werkzeug是一个工具包,并不是web服务器,也不是web框架,但可以为web框架提供底层工具库
- Werkzeug一个常用的功能是封装了请求,返回,路由等功能, python的很多web后台直接可以 使用request, response, router
- 正是有了WSGI规范,并且有了一个很好的工具包Werkzeug,我们再写一个web框架就贼简单,啥都 不用处理,只关注业务处理就好,所以,python的后台框架有点多~~~~
Werkzeug库的routing模块负责实现URL解析,routing模块内部有:
- Rule类: 用来构造不同的URL模式的对象,路由URL规则
- Map类: 存储所有的URL规则和一些配置参数
- BaseConverter的子类: 负责定义匹配规则
- MapAdapter类: 负责协调Rule做具体的匹配的工作