4、Flask实战第4天:自定义url转换器
url传参可以限定参数的数据类型,例如:限定user_id数据类型为int
@app.route('/user/<int:user_id>') def my_list(user_id): return '您输入的user_id为:{}'.format(user_id)
当我们传递的参数不是int类型的时候,页面访问该url就会返回404错误,我们可以来看下flask是如何定义这些数据类型的
首先导入BaseConverter
from werkzeug.routing import BaseConverter
按住ctrl用户鼠标点击BaseConverter进去查看源码,可以发现BaseConverter是一个基类,下面很多子类继承了它,这些子类是
UnicodeConverter
AnyConverter
PathConverter
NumberConverter
IntegerConverter
FloatConverter
UUIDConverter
往下看,可以看出这些都是默认的数据类型
#: the default converter mapping for the map. DEFAULT_CONVERTERS = { 'default': UnicodeConverter, 'string': UnicodeConverter, 'any': AnyConverter, 'path': PathConverter, 'int': IntegerConverter, 'float': FloatConverter, 'uuid': UUIDConverter, }
通过源码,我们知道这些就是flask给我们定义的数据类型,这些子类都是继承BaseConverter,然后利用正则来匹配
了解这些后,我们就可以自定义数据类型了
需求:一个url中,含有手机号码的参数,必须限定这个参数满足手机号码的格式
from werkzeug.routing import BaseConverter ... class TelephoneConveter(BaseConverter): regex = r'1[3458]\d{9}' # 这里是定义数据类性的名字,并注册到url_map中 app.url_map.converters['tel'] = TelephoneConveter #然后我们就可以使用自定一的tel类型了 @app.route('/my_tel/<tel:telephone>') def my_tel(telephone): return '您的手机号码是:{}'.format(telephone)
to_python
这个方法的返回值,将会传递到view函数中作为参数
现在有个需求:访问127.0.0.1/posts/a+b能够显示出a和b的所有帖子
根据需求,我们知道需要把参数a+b解析出来,并通过数据库去查询,这里不去讨论数据库这块,只是来怎么分解a+b
@app.route('/posts/<boards>') def posts(boards): borads = boards.split('+') #borads现在是一个列表,很容易取出a,b的值 return str(borads)
上面的方法虽然可以实现,但是如果用到的类似场景较多的时候,我们还要再写一遍,每次写就比较麻烦,这时候我们就可以利用to_python来实现
class ListConveter(BaseConverter): def to_python(self, value): #这个value就是我们url的参数 return value.split("+") #这个返回值,就是我们视图函数接收到的参数 app.url_map.converters['list'] = ListConveter @app.route('/posts/<list:boards>') def posts(boards): #这里的borads已经被list处理了,变成了列表 return str(borads)
to_url
这个方法的返回值,将会在调用url_for函数的时候生成符合要求的url形式
class ListConveter(BaseConverter): def to_python(self, value): return value.split("+") def to_url(self, value): return '+'.join(value) app.url_map.converters['list'] = ListConveter @app.route('/') def hello_world(): return url_for('posts', boards=['a', 'b']) @app.route('/posts/<list:boards>') def posts(boards): return str(boards)
每天进步一点,加油!