Flask初探二( app.route 内部实现)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask初探二( app.route 内部实现)相关的知识,希望对你有一定的参考价值。

参考技术A

上一篇blog 探究了flask 各个参数的作用,本篇将围绕 @app.route(\'/\') 探究一下flask 做了些什么

route 源码

route 实际上是一个闭包, 路径规则通过route 方法被rule 形参引用, 然后返回decorator 方法,所以@app.route(\'/\') <==>@decorator , 所以 hello_world =decorator (hello_world ) <==> hello_world .
@app.route(\'/\') 的主要作在于 endpoint = options.pop(\'endpoint\', None) 和 self.add_url_rule(rule, endpoint, f, **options) 两句.

add_url_rule 源码

从方法注释可以看到另外一种可以将url 规则和试图函数绑定的方式

通过装饰器注册路由, 一般情况下 endpoint 等于None, 所以endpoint = _endpoint_from_view_func(view_func).

_endpoint_from_view_func

通过查看_endpoint_from_view_func方法, 可以知道endpoint = view_func.__name__, 既通过装饰器注册路由,一般情况下 endpoint 等于方法名.

实验
一般情况下 view_func 是没有methods 属性的, 通过修改源码方便实验
源码

demo.py

实验结果

通过上面的结果可以看出

分析

通过这两句可以得出一个结论, methods 通过键值对形式赋值, 除了methods = "POST" 的形式之外的所有可迭代的容器都可以作为值.

源码

实验
源码改造

demo.py

结果

通过实验可以得出,

源码

实验
源码改动

demo.py

实验结果

总结:

到此结  DragonFangQy 2018.6.20

Flask 学习之 路由

一.路由的基本定义

# 指定访问路径为 demo1

@app.route(‘/demo1‘)

def demo1():

    return ‘demo1‘

二.常用路由设置方式

@app.route(‘/user/<username>‘)   #常用的   不加参数的时候默认是字符串形式的

@app.route(‘/post/<int:post_id>‘)  #常用的   #指定int,说明是整型的

@app.route(‘/post/<float:post_id>‘)

@app.route(‘/post/<path:path>‘)

@app.route(‘/login‘, methods=[‘GET‘, ‘POST‘])

三.路由可以设置传递参数, 2种方式

1.一种为路由传递参数[没有限定类型]

2.路由传递参数[限定数据类型]

以下为相应的例子:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = "hsz"

from flask import Flask

app = Flask(__name__)


# 加载项目配置
# 配置类
class Config(object):
    DEBUG = True


app.config.from_object(Config)


# 路由传递参数[没有限定类型]
@app.route(/user/<user_id>)
def user_info_1(user_id):
    return hello info_1 %s % user_id


# 路由传递参数[限定数据类型],列子是用了int类型,可以选择bool,float都可以的
# user_id 必须是整数
@app.route(/user/<int:user_id>)
def user_info_2(user_id):
    return hello info_2 %d % user_id


if __name__ == __main__:
    app.run(host=127.0.0.1, port=9000)
    """
    测试说明:
        测试1:
        http://127.0.0.1:9000/user/qwer
        这样的情况是访问了函数1的url,因为qwerb不为整数,所以路由到没有限定类型处
        测试2:
        http://127.0.0.1:9000/user/2
        这样的情况下会选择有限定类型的路由
        测试3:
        注释限定的,让后使用如下url测试:
        http://127.0.0.1:9000/user/2
        这样会走无限定的路由
"""

四.路由之url_for()函数

1.给指定的函数构造URL

#例1:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = "hsz"

from flask import Flask, url_for
from flask import redirect

app = Flask(__name__)


@app.route(/index)  # endpoint是别名
def home():
    """
    url_for是个函数接受视图函数的名字(字符串形式)作为参数,返回视图函数对应的url
    通过url_for home 来获取前端输入的url是什么
    :return:
    """
    v = url_for("home")
    print(v)
    return "index"

# url_for() 使用endpoint ,通过反向机制构建URL路径 
@app.route(/index/<int:nid>, endpoint="aaa")  # endpoint是别名
def zzz(nid):
    """
    这边使用了别名,将zzz函数别名为aaa
    所以url_for 对的是aaa
    :param nid:
    :return:
    """
    v = url_for("aaa", nid=nid)
    print(v)
    return "index2"


if __name__ == __main__:
app.run(host=127.0.0.1, port=9000)

2.访问静态文件(CSS / JavaScript )

只要在你的包中或是模块的所在目录中创建一个名为 static 的文件夹,在应用中使用 /static 即可访问。

url_for(‘static‘, filename=‘style.css‘)

这个文件应该存储在文件系统上的 static/style.css

五.路由的正则匹配方式

1.自定义转换器实现

web 开发中,可能会出现限制用户访问规则的场景,那么这个时候就需要用到正则匹配,根据自己的规则去限定请求参数再进行访问

具体实现步骤为:

(1)导入转换器基类:在 Flask 中,所有的路由的匹配规则都是使用转换器对象进行记录

(2)自定义转换器:自定义类继承于转换器基类

(3)添加转换器到默认的转换器字典中

(4)使用自定义转换器实现自定义匹配规则

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = "hsz"

# 下面编写一个自定义路由转换器

from flask import Flask

app = Flask(__name__)

# 导入转换器基类
from werkzeug.routing import BaseConverter


class MobileNumberConverter(BaseConverter):
    """
    手机号码的自定义路由转换器
    """
    regex = "d{11}"


# 添加转换器到默认的转换器字典中,并指定转换器使用时名字为: mobile
app.url_map.converters[mobile] = MobileNumberConverter


# 使用转换器去实现自定义匹配规则
@app.route(r"/sms/<mobile:mobile_number>/")  # mobile_number就是测试的电话号码
def sms(mobile_number):
    """
    通过以下url访问:
    http://127.0.0.1:9000/sms/13666666666/
    :param mobile_number:
    :return:
    """
    print(mobile_number)
    return "手机号通过,短信"


# 例2
class RegexConverter(BaseConverter):
    """正在路由转换器"""

    def __init__(self, url_map, *args):
        # super().__init__(url_map)  # 或者这样写
        # url_map 所有url组成的元组
        super(RegexConverter, self).__init__(url_map)  # 初始化分类
        self.regex = args[0]  # 是一个元组


app.url_map.converters[reg] = RegexConverter


# w 表示大写字母小写字母下划线
@app.route(r"/register/<reg(‘w{4,6}‘):username>/")
def reg(username):  # 这个函数名没有限制
    """
    通过以下url访问:
    http://127.0.0.1:9000/register/qwer/
    :param username:
    :return:
    """
    print(username)
    return "ok reg"


if __name__ == "__main__":
    app.run(host=0.0.0.0, port=9000)

 

2.系统自带转换器

在werkzeug.routing.py源文件中

 

DEFAULT_CONVERTERS = {
    "default": UnicodeConverter,
    "string": UnicodeConverter,
    "any": AnyConverter,
    "path": PathConverter,
    "int": IntegerConverter,
    "float": FloatConverter,
    "uuid": UUIDConverter,
}

 

以上类型都是系统自带的。

系统自带的转换器具体使用方式在每种转换器的注释代码中有写,请留意每种转换器初始化的参数。

以上是关于Flask初探二( app.route 内部实现)的主要内容,如果未能解决你的问题,请参考以下文章

flask框架: 实现支持正则的路由

Flask 入门

这不是魔法:Flask和@app.route

Flask

Flask路由

Flask 学习之 路由