专栏首页Devops专栏Flask URL默认转换器、自定义转换器、to_python、to_url

Flask URL默认转换器、自定义转换器、to_python、to_url

Flask框架自带的转换器类型

  • int转换器 <int:param> :接收整数
  • float转换器 <float:param>: 接收浮点数
  • string转换器 <string:param>: 接收string类型(默认则是string转换器
  • path转换器 <path:param>:和默认的相似,但也接收斜线

设置int类型的路径参数

# 转换器 <int:goods_id>
@app.route('/goods_info/<int:goods_id>')
def goods_info(goods_id):
    return "goods_id is %d" % goods_id

测试访问 http://127.0.0.1:5000/goods_info/123

设置float转换器的路径参数

# 设置float转换器
@app.route('/goods_info/<float:goods_id>') 
def goods_info(goods_id):
    return "goods_id is %s" % goods_id

可以发现参数为float参数是能够正常访问处理的。

当传递参数为 123 整数的时候,则报错Not Found

当传递参数为 hello 字符串的时候,则报错Not Found

设置string类型的路径参数

# 设置转换器 <string:goods_id>
@app.route('/goods_info/<string:goods_id>') 
def goods_info(goods_id):
    return "goods_id is %s" % goods_id

测试访问 http://127.0.0.1:5000/goods_info/你好

可以看到中文的字符串参数也是可以直接获取的。

  • 其中如果转换器不写类型,默认就是string类型的,示例如下:
# 设置转换器 默认是string
@app.route('/goods_info/<goods_id>') 
def goods_info(goods_id):
    return "goods_id is %s" % goods_id

设置path转换器的路径参数

# 设置path转换器
@app.route('/goods_info/<path:goods_id>') 
def goods_info(goods_id):
    return "goods_id is %s" % goods_id

测试访问:http://127.0.0.1:5000/goods_info/hello//world/123

可以看到 path转换器 可以接收斜杠 / 将后面所有的字符串都作为参数传递。

上面的这几种Flask自带的转换器虽然可以设置很多参数了,但是还是无法匹配一些特殊需求的路径参数。

例如:在发送短信的URL中,路径参数设置为手机号码,上面的自带类型就无法精确匹配手机号码了。

这时候就需要自定义路由转换器出场了。

自定义路由转换器

1.自定义路由转换器的基础类:

from werkzeug.routing import BaseConverter

2.创建自定义转换器,以及将转换器加入Flask应用中:

# 创建自定义转换器
# 1. 定义自己的转换器
class RegexConverter(BaseConverter):
    """"""
    def __init__(self, url_map, regex):
        """
        :param url_map: 固定传递的参数,用于调用父类的初始化方法 
        :param regex: 从url使用()传递过来的正则参数
        """
        # 调用父类的初始化方法
        super(RegexConverter, self).__init__(url_map)
        # 将正则表达式的参数保存到对象的属性中,flask会去使用这个属性来进行路由的正则匹配
        self.regex = regex

# 2. 将自定义的转换器添加到flask的应用中
app.url_map.converters["re"] = RegexConverter

3.在视图函数中设置自定义路由转换器re:

# 127.0.0.1:5000/send/18912345678
# <re(r''): param> 使用re自定义转换器,其中()则是需要传递的参数
@app.route("/send/<re(r'1[34578]\d{9}'):mobile_num>") 
def send_sms(mobile_num):
    return "send sms to %s" % mobile_num

4.测试访问符合正则匹配的电话号码的url

访问 http://127.0.0.1:5000/send/18912345678

5.测试访问不符合正则匹配的url

访问 http://127.0.0.1:5000/send/189123

根据不符合正则匹配的URL参数,则报错Not Found。从效果来看,就可以知道通过这个自定义的转换器,我们可以实现这种特殊的参数获取。

创建专属手机号码的转换器

上面的转换器可以传递正则匹配的规则,属于一种万能转换器,下面将其创建一个专属手机号码的转换器。

# 创建Moblie的专属转换器
class MobileConverter(BaseConverter):

    def __init__(self,url_map):
        # super(MobileConverter,self).__init__(url_map) # 调用父类方法一
        super().__init__(url_map) # 调用父类方法二
        self.regex = r'1[34578]\d{9}'

# 注册MobileConverter转换器
app.url_map.converters["mobile"] = MobileConverter

# 设置视图函数
@app.route("/send/<mobile:mobile_num>")
def send_sms(mobile_num):
    return "send sms to %s" % mobile_num

其实这个例子主要是想说明Flask可以创建多个自定义转换器。

另外,在Django中有中间类这个类方法来处理url请求至视图函数之间的业务处理,例如:权限验证,session数据记录等等。

在Flask中可以使用专属转换器的to_pythonto_url两个函数来实现类似中间类这样的功能。

下面来看看。

查看BaseConverter类中的源码

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))

首先从源码来分析一下这个继承类中to_pythonto_url函数。

  • to_python 将url传递的参数,直接将其传递至视图函数之中
  • to_url 则是当另一个视图函数使用 url_for() 这个方法跳至该转换器的时候,会将url的参数传递到url路径的参数中。

单单这么解释有些抽象,下面来看看示例。

to_python 函数

# 创建Moblie的专属转换器
class MobileConverter(BaseConverter):

    def __init__(self,url_map):
        # super(MobileConverter,self).__init__(url_map)
        super().__init__(url_map)
        self.regex = r'1[34578]\d{9}'

    def to_python(self, value):
        """"""
        print("to_python方法被调用")
        # value是在路径进行正则表达式匹配的时候提取的参数
        return "abc" # 该value会传递到视图函数中

app.url_map.converters["mobile"] = MobileConverter

@app.route("/send/<mobile:mobile_num>")
def send_sms(mobile_num):
    return "send sms to %s" % mobile_num

此时测试访问 http://127.0.0.1:5000/send/18912345678

按照原来访问后在浏览器会打印 send sms to 18912345678 的信息,但是由于to_python 设置返回是 "abc",所以浏览器将会打印 send sms to abc,下面来浏览器执行验证看看,如下:

从浏览器就可以判断出to_python方法就是url传递到视图函数中间的业务处理方法,其实就相当于Django的中间类。

如果有权限验证类的需求,可以在to_python中实现。

to_url 函数

# 创建Moblie的专属转换器
class MobileConverter(BaseConverter):

    def __init__(self,url_map):
        # super(MobileConverter,self).__init__(url_map)
        super().__init__(url_map)
        self.regex = r'1[34578]\d{9}'

    def to_python(self, value):
        """"""
        print("to_python方法被调用")
        # value是在路径进行正则表达式匹配的时候提取的参数
        return value # 该value会传递到视图函数中

    def to_url(self, value):
        """使用url_for的方法的时候被调用"""
        print("to_url方法被调用")
        return "15811111111" # 该value会修改url路径中的参数为 15811111111

app.url_map.converters["mobile"] = MobileConverter

@app.route("/send/<mobile:mobile_num>")
def send_sms(mobile_num):
    return "send sms to %s" % mobile_num

@app.route("/hello_send")
def hello_send():
    return redirect(url_for('send_sms', mobile_num=18612345678))

这个示例是首先访问 hello_send 视图函数,然后使用 url_for函数跳转至 send_sms 视图函数。

在这种过程中,hello_send 视图函数跳转的时候设置的路径参数为 mobile_num=18612345678

那么正常在浏览器转发后的url访问应该是:http://127.0.0.1:5000/send/18612345678

但是由于to_url返回的是15811111111,所以最终跳转的url显示会是 http://127.0.0.1:5000/send/15811111111

下面来确认看看,访问http://127.0.0.1:5000/hello_send

可以从图中的传递说明,应该基本上都可以看出参数的传递过程。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 腾讯云服务器搭建ApachePHPMySQL环境

    对于服务器来说稳定、极速就选择 2核 4G内存配置的云服务器比较稳妥。这个配置跑网站是比较轻松无压力的。配上 avada主题,可以做出的很大气、高大上的企业网站...

    用户6580788
  • TP漏洞之文件上传总结

    一般都是在网页上写一段javascript脚本,校验上传文件的后缀名,有白名单形式也有黑名单形式。

    php007
  • 300万知乎用户数据如何大规模爬取?如何做数据分析?

    很早就有采集知乎用户数据的想法,要实现这个想法,需要写一个网络爬虫(Web Spider)。因为在学习 python,正好 python 写爬虫也是极好的选择,...

    机器学习AI算法工程
  • Etcd 配置详解

    对于标记 --my-flag 环境变量的格式是 ETCD_MY_FLAG。 适用于所有标记。

    用户5760343
  • 腾讯云服务器上部署LNMP环境

    最近在学Laravel,同参考文章,本来只是在虚拟机上运行,但现在正好因为手上有腾讯云服务器,所以就直接拿来部署Laravel。

    用户6468650
  • 反间谍之旅:针对伊朗的网络之战

    “土耳其轰炸美盟友”、“伊朗游轮被炸”等一系列的重大事件的发生无疑显示出中东地区紧张的局势。此时此刻的中东犹如一个桶,一不小心就会出现战争风险。不过,中东局势虽...

    FB客服
  • Etcd 运行时重配置

    1、更新:要更新 peer URL,首先,我们需要找到目标成员的ID。 etcdctl member list 6e3bd23ae5f1eae0: name...

    用户5760343
  • CentOS 5/6下安装Axel插件加速yum下载

    axel插件是基于yum下的一个多线程下载插件,通过打开多个HTTP/FTP连接来将一个文件进行分段下载,从而达到加速下载的目的。对于下载大文件,该工具特别有用...

    孙杰
  • Jira服务工作台路径遍历导致的敏感信息泄露漏洞分析

    本文中,作者通过对JIRA Servcie Desk应用下普通用户和管理员账户的权限测试,发现可以普通用户身份访问获取到管理员账户关键路径下的一些敏感信息,这些...

    FB客服
  • 令人惊叹的前端路由原理解析和实现方式

    ? 在单页应用如此流行的今天,曾经令人惊叹的前端路由已经成为各大框架的基础标配,每个框架都提供了强大的路由功能,导致路由实现变的复杂。想要搞懂路由内部实现还是...

    腾讯技术工程官方号

扫码关注云+社区

领取腾讯云代金券