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,
}
View Code

通过源码,我们知道这些就是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)

posted @ 2018-06-29 16:24  sellsa  阅读(1548)  评论(3编辑  收藏  举报