Python语言:Flask 应用中的 URL 处理
小标 2018-07-16 来源 : 阅读 1588 评论 0

摘要:本文主要向大家介绍了Python语言:Flask 应用中的 URL 处理,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助。

本文主要向大家介绍了Python语言:Flask 应用中的 URL 处理,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助。

在文章:一个Flask应用运行过程剖析中,在一个上下文环境中可以处理请求。如果不考虑在处理请求前后做的一些操作,Flask源码中真正处理请求的是dispatch_request()方法。其源码如下:

Python

   

def dispatch_request(self):

    """Does the request dispatching.  Matches the URL and returns the

    return value of the view or error handler.  This does not have to

    be a response object.  In order to convert the return value to a

    proper response object, call :func:`make_response`.

    """

    try:

        endpoint, values = self.match_request()

        return self.view_functions[endpoint](**values)

    except HTTPException, e:

        handler = self.error_handlers.get(e.code)

        if handler is None:

            return e

        return handler(e)

    except Exception, e:

        handler = self.error_handlers.get(500)

        if self.debug or handler is None:

            raise

        return handler(e)

   

从上面的源码中可以看到,dispatch_request()方法做了如下的工作:

1. 对请求的URL进行匹配;

2. 如果URL可以匹配,则返回相对应视图函数的结果;

3. 如果不可以匹配,则进行错误处理。

对于错误的处理,本文暂不做介绍。本文主要对Flask应用的URL模式以及请求处理过程中的URL匹配进行剖析。

Flask应用的url_map

Flask应用实例化的时候,会为应用增添一个url_map属性。这个属性是一个Map类,这个类在werkzeug.routing模块中定义,其主要的功能是为了给应用增加一些URL规则,这些URL规则形成一个Map实例的过程中会生成对应的正则表达式,可以进行URL匹配。相关的概念和内容可以参考:Werkzeug库——routing模块。

在Flask源码中,它通过两个方法可以很方便地定制应用的URL。这两个方法是:route装饰器和add_url_rule方法。

1. add_url_rule

Python

def add_url_rule(self, rule, endpoint, **options):

    options['endpoint'] = endpoint

    options.setdefault('methods', ('GET',))

    self.url_map.add(Rule(rule, **options))

   

add_url_rule方法很简单,只要向其传递一条URL规则rule和一个endpoint即可。endpoint一般为和这条URL相关的视图函数的名字,这样处理就可以将URL和视图函数关联起来。除此之外,还可以传递一些关键字参数。调用该方法后,会调用Map实例的add方法,它会将URL规则添加进Map实例中。

2. route装饰器

为了更加方便、优雅地写应用的URL,Flask实现了一个route装饰器。

Python 

def route(self, rule, **options):

    def decorator(f):

        self.add_url_rule(rule, f.__name__, **options)

        self.view_functions[f.__name__] = f

        return f

    return decorator

   

route装饰器会装饰一个视图函数。经route装饰的视图函数首先会调用add_url_rule方法,将装饰器中的URL规则添加进Map实例中,视图函数的名字会作为endpoint进行传递。然后在该应用的view_functions中增加endpoint和视图函数的对应关系。这种对应关系可以在请求成功时方便地调用对应的视图函数。

3. 一个简单的例子

我们用一个简单的例子来说明以上过程的实现:

Python

>>> from flask import Flask

>>> app = Flask(__name__)

>>> @app.route('/')

    def index():

        return "Hello, World!"

>>> @app.route('/<username>')

    def user(username):

        return "Hello, %s" % username

>>> @app.route('/page/<int:id>')

    def page(id):

        return "This is page %d" % id

   

以上代码,我们创建了一个Flask应用app,并且通过route装饰器的形式为app增加了3条URL规则。

首先: 我们看一下Flask应用的url_map长啥样:

Python

>>> url_map = app.url_map

>>> url_map

Map([<Rule '/' (HEAD, GET) -> index>,

     <Rule '/static/<filename>' -> static>,

     <Rule '/page/<id>' (HEAD, GET) -> page>,

     <Rule '/<username>' (HEAD, GET) -> user>

    ])

   

可以看到,url_map是一个Map实例,这个实例中包含4个Rule实例,分别对应4条URL规则,其中/static/<filename>在Flask应用实例化时会自动添加,其余3条是用户创建的。整个Map类便构成了Flask应用app的URL“地图”,可以用作URL匹配的依据。

接下来: 我们看一下url_map中的一个属性:_rules_by_endpoint:

Python

   

>>> rules_by_endpoint = url_map._rules_by_endpoint

>>> rules_by_endpoint

{'index': [<Rule '/' (HEAD, GET) -> index>],

'page': [<Rule '/page/<id>' (HEAD, GET) -> page>],

'static': [<Rule '/static/<filename>' -> static>],

'user': [<Rule '/<username>' (HEAD, GET) -> user>]

}

   

可以看出,_rules_by_endpoint属性是一个字典,反映了endpoint和URL规则的对应关系。由于用route装饰器创建URL规则时,会将视图函数的名字作为endpoint进行传递,所以以上字典的内容也反映了视图函数和URL规则的对应关系。

再接下来: 我们看一下Flask应用的view_functions:

Python

>>> view_functions = app.view_functions

>>> view_functions

{'index': <function __main__.index>,

'page': <function __main__.page>,

'user': <function __main__.user>

}

   

在用route装饰器创建URL规则时,它还会做一件事情:self.view_functions[f.__name__] = f。这样做是将函数名和视图函数的对应关系放在Flask应用的view_functions。由于Map实例中存储了函数名和URL规则的对应关系,这样只要在匹配URL规则时,如果匹配成功,只要返回一个函数名,那么便可以在view_functions中运行对应的视图函数。

最后: 我们看一下URL如何和Map实例中的URL规则进行匹配。我们以/page/<int:id>这条规则为例:

Python 

>>> rule = url_map._rules[2]

>>> rule

<Rule '/page/<id>' (HEAD, GET) -> page>

>>> rule._regex

re.compile(ur'^\|\/page\/(?P<id>\d+)$', re.UNICODE)

>>> rule._regex.pattern

u'^\\|\\/page\\/(?P<id>\\d+)$'

   

可以看到,在将一条URL规则的实例Rule添加进Map实例的时候,会为这个Rule生成一个正则表达式的属性_regex。这样当这个Flask应用处理请求时,实际上会将请求中的url和Flask应用中每一条URL规则的正则表达式进行匹配。如果匹配成功,则会返回endpoint和一些参数,返回的endpoint可以用来在view_functions找到对应的视图函数,返回的参数可以传递给视图函数。具体的过程就是:

Python

   

try:

    # match_request()可以进行URL匹配

    endpoint, values = self.match_request()

    return self.view_functions[endpoint](**values)

    ...

本文由职坐标整理并发布,了解更多内容,请关注职坐标编程语言Python频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 1
看完这篇文章有何感觉?已经有2人表态,50%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程