源码解析flask的路由系统_蜘蛛资讯网 亚博娱乐登录不了了,亚博体育yabo88在线,亚博体育app下载苹果版
作者:百年不渡??分类:未来幻想??点击:91次??下载:9807889次??大小:70M??日期:2019-09-17

巴音郭楞栋鸭粗工贸有限公司_源码解析flask的路由系统

当我们新建一个flask项目时,pycharm通常已经为项目定义了一个基本路由

@app.route("/")
def hello_world():
    return "Hello World!"

此时在浏览器中输入地址http://127.0.0.1:5000,页面会显示出"Hello World!"的字样

如下图所示

那么此时在flask后台程序中,到底发生了什么事情呢??

在上面的例子中,可以看到对hello_world视图函数被app.route这个有参装假器装饰

来看下app.route这个有参装饰器的内部实现原理

app是Flask主程序的类实例化本项目名得到的一个对象

app = Flask(__name__)

然后调用app对象的route方法来装饰hello_world视图函数

route方法的源码:

def route(self, rule, **options):
    def decorator(f):
        endpoint = options.pop("endpoint", None)
        self.add_url_rule(rule, endpoint, f, **options)
        return f
    return decorator

在用app.route装饰hello_world视图函数的时候,实际上app.route中还可以添加一些参数。

比如指定请求的方法的变量:methods=["GET","POST"]以及指定视图函数的endpoint,相当于Django中视图函数的别名等

在这里,rule参数相当于hello_world视图函数中的"/"路径,options参数中包含methods和endpoint等

在route装饰器里,返回decorator闭包函数。

在decorator闭包函数中,先从options中获取endpoint的值,endpoint的值默认为None

然后调用self.add_url_rule内部方法处理传递的参数rule,endpoint,f等,在这里self指的是app这个对象

查看app对象中的add_url_rule方法:

    @setupmethod
    def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
    
        if endpoint is None:
            endpoint = _endpoint_from_view_func(view_func)
        options["endpoint"] = endpoint
        methods = options.pop("methods", None)
    
        # if the methods are not given and the view_func object knows its
        # methods we can use that instead.  If neither exists, we go with
        # a tuple of only ``GET`` as default.
        if methods is None:
            methods = getattr(view_func, "methods", None) or ("GET",)
        if isinstance(methods, string_types):
            raise TypeError("Allowed methods have to be iterables of strings, "
                            "for example: @app.route(..., methods=["POST"])")
        methods = set(item.upper() for item in methods)
    
        # Methods that should always be added
        required_methods = set(getattr(view_func, "required_methods", ()))
    
        # starting with Flask 0.8 the view_func object can disable and
        # force-enable the automatic options handling.
        provide_automatic_options = getattr(view_func,
            "provide_automatic_options", None)
    
        if provide_automatic_options is None:
            if "OPTIONS" not in methods:
                provide_automatic_options = True
                required_methods.add("OPTIONS")
            else:
                provide_automatic_options = False
    
        # Add the required methods now.
        methods |= required_methods
    
        rule = self.url_rule_class(rule, methods=methods, **options)
        rule.provide_automatic_options = provide_automatic_options
    
        self.url_map.add(rule)
        if view_func is not None:
            old_func = self.view_functions.get(endpoint)
            if old_func is not None and old_func != view_func:
                raise AssertionError("View function mapping is overwriting an "
                                     "existing endpoint function: %s" % endpoint)
            self.view_functions[endpoint] = view_func

可以看到,当在视图函数中没有指定endpoint时,程序会调用_endpoint_from_view_func方法为endpoint赋值

def _endpoint_from_view_func(view_func):
    assert view_func is not None, "expected view func if endpoint " 
                                  "is not provided."
    return view_func.__name__

可以看出,_endpoint_from_view_func实际上返回的就是view_func函数的函数名。

在上面的例子中,view_func指的是hello_world这个视图函数

所以此时,在options这个字典中有一个键为endpoint,对应的值为view_func函数的函数名

接着,程序从options字典中弹出"methods"的值,并对methods中的每个方法转换为大写,如果methods没有从程序中获取,则默认为"GET"

接着,程序从函数中获取"required_methods"的值,并进行去重,默认得到一个空集合

再对methods和required_methods进行"|="操作,也就是按位或运算

    |=(按位或)运算
    
    >>> a = 15
    >>> bin(a)
    "0b1111"
    >>> b = 100
    >>> bin(b)
    "0b1100100"
    >>> a |= b
    >>> a
    111
    >>> bin(a)
    "0b1101111"
    >>> 0b1101111
    111
    
    先把a这个十进制数转换成二进制,得到1111
    再把b这个十进制数转换成二进制,得到1100100
    
    对a和b的二进制格式进行按位或运算
    
    a   000  0111
    b   110  0100
        110  0111
    
    因为a转换成二进制只有四位,如果要和b的二进制格式做位运算,则必须在头部填充0到和b的二进制相同的长度,得到"0000111"
    
    或运算中,只要有一个数为1,则这一位上做或运算的结果就为1
    所以上面两个数做或运算得到的二进制数为"0b1100111"
    把这个二进制数转换成十进制,则为111,把111这个十进制数赋值给a

对methods和required_methods进行按位或运算,实际上就是把required_methods的值添加到methods方法集合里

接着程序调用self.url_rule_class方法处理rule(也就是"/"),methods和options字典

得到rule这个对象,在这里self同样指的是app这个对象

可以看到,url_rule_class指向的是Rule这个类的内存地址

url_rule_class = Rule

然后用Map类实例化得到self.url_map对象,调用self.url_map对象中的add方法处理rule这个对象

self.url_map = Map()

分析了上面的app.route的流程,知道使用app对象的route方法装饰rule,实际上就是执行了add_url_rule这个方法

那如果定义一个视图函数,调用app对象中的add_url_rule方法来处理对应的rule,是不是也可以完成route的装饰器功能呢

    from flask import Flask
    app = Flask(__name__)
    
    @app.route("/")
    def hello_world():
        return "Hello World!"
    
    def login():
        return "登录成功!!"
    
    app.add_url_rule("/login",endpoint=None,view_func=login,methods=["GET"])

启动这个项目,在浏览器中打开"http://127.0.0.1:5000/login"地址,

得到的效果如下

由些我们可以知道,虽然flask的路由实现表面上是使用了route这个装饰器,实际上内部也是调用app对象中的add_url_rule方法来实现,类似于Django中中路由的用法

you xie wo men ke yi zhi dao, sui ran flask de lu you shi xian biao mian shang shi shi yong le route zhe ge zhuang shi qi, shi ji shang nei bu ye shi diao yong app dui xiang zhong de add_url_rule fang fa lai shi xian, lei si yu Django zhong zhong lu you de yong fa

当前文章:http://www.psf54.com/jd4qi/65081-236901-10480.html

发布时间:04:58:09

六合历史开奖结果??诸葛神坛平特一肖??彩库宝典??www.25829.com??423888.com??www.47748.com??马邦高手联盟35538??金石高手论坛??139kj开奖??www.25000.com??

您可能还对以下电子书感兴趣

巴音郭楞栋鸭粗工贸有限公司TXT下载声明:

1 蜘蛛资讯网免费提供的巴音郭楞栋鸭粗工贸有限公司,均由网友上传,供下载测试之用,不作商业用途,下载后请二十四小时后删除!

2 我们根据txt小说全文所整理出巴音郭楞栋鸭粗工贸有限公司txt电子书全集免费下载,由程序自动生成巴音郭楞栋鸭粗工贸有限公司txt下载文件。

3 书友所发表的txt小说巴音郭楞栋鸭粗工贸有限公司的相关评论,并不代表本站赞同巴音郭楞栋鸭粗工贸有限公司txt下载或者支持巴音郭楞栋鸭粗工贸有限公司的读者观点。

4 如果发现小说《巴音郭楞栋鸭粗工贸有限公司txt全集》无法下载未及时更新请联系我们。如果您喜欢巴音郭楞栋鸭粗工贸有限公司txt电子书,请支持作者到书店购买正版图书。感谢您的合作与支持。

5 好看的小说巴音郭楞栋鸭粗工贸有限公司是作者"百年不渡"的最新力作,巴音郭楞栋鸭粗工贸有限公司电子书由网友发布;小说巴音郭楞栋鸭粗工贸有限公司版权属于作者所有,如果侵犯您的利益,请通知我们。