from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
我觉得只要稍微看过 Flask 官方教程的小伙伴都会对这个代码很熟悉,熟悉归熟悉,那小伙伴们理解 **@app.route()**是如何发挥作用的吗?如果不清楚的话,嗯哼,just follow me~~
在理解这个之前,我们需要做一些准备。
@app.route 和 装饰器
为了理解 @app.route() 是如何发挥作用的,我们首先需要对 Python 中的装饰器有个大体的认识。具体的可以参考廖老师的教程--装饰器。老实说,装饰器其实就是在一个函数内部定义另外一个函数,然后返回一个新的函数,即动态的给一个对象添加额外的职责。如果还不是很明白的话,没关系,我们来看看具体的例子。
def simple_decorator(f):
def wrapper():
print "func enter"
f()
print "func exit"
return wrapper
@simple_decorator
def hello():
print "Hello World!"
hello()
运行一下上述代码,我们将会看到如下的输出:
看完这个例子,小伙伴们有没有稍微理解一点 @app.route() 了呢?可能有的小伙伴会说,@app.route() 是带参的,我们的装饰器并没有任何参数,这个很简单,接下来让我们试着,让我们的装饰器也可以传递参数。
def not_very_simply_decorator(enter_msg,exit_msg):
def simple_decorator(f):
def wrapper():
print enter_msg
f()
print exit_msg
return wrapper
return simple_decorator
@not_very_simply_decorator("func enter","func exit")
def hello():
print "Hello World"
hello()
是不是很奇怪,我为啥让两次的输出信息都一样,因为那样子,我只需要截一次图了~~哈哈,有没有觉得这个跟 app.route() 越来越有点像了,有的小伙伴肯定要说了,人家是 app.route(),而我的是 func(),那我只能说,咱们再接着往下看。
从 route() 到 app.route()的不归路
在此之前,如果有小伙伴跟我一样用 Pycharm 的话,使用它直接创建一个 Flask 项目,然后去点击 app.route()的话,会发现它跳转到了一个 Flask.py 的文件内,这个文件内容是一个 Flask 对象,而我们的 route() 函数就在其中,为了更好的理解 Flask 对象,我们可以尝试模仿它,创建一个类似的 Flask 对象。
class FlaskBother():
def route(self,route_str):
def decorator(f):
return f
return decorator
app = FlaskBother()
@app.route('/')
def hello():
return 'Hello World'
看到这里,我就问一句,像不像?这个和我们之前创建的装饰器的主要区别在于,我们不想去修改我们装饰的这个函数的功能,我们只想去引用它,so 重点来了,聪明的你们知道,我们需要什么吗~~我们需要一个变量去存储路由和其关联的函数。那么 Flask 有没有这个变量呢,答案是肯定的,那我们如何在 Flask 中去查看所有的路由,以最初的最小的 Flask 为例。
进入Python交互模式
>>> from Hello import app
>>> app.url_map
Map([<Rule '/' (HEAD, OPTIONS, GET) -> hello>,
<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>])
好了说完在 Flask 中如何查看所有路由,为了在我们的 FlaskBother实现同样的功能,我们添加一个 "route" 字典到我们 FlaskBother 对象中。当我们的装饰器被调用的时候,我们将路由和关联的函数保存到我们的 "route" 字典中去。
class FlaskBother():
def __init__(self):
self.routes = {}
def route(self,route_str):
def decorator(f):
self.routes[route_str] = f
return f
return decorator
app = FlaskBother()
@app.route("/")
def hello()
return "Hello World"
其实到这里我们基本上已经完成了百分之90%了,我们现在唯一欠缺是一个可以访问内部 route 的途径,所以让我们再添加一个函数 server(path),通过这个函数我们可以通过路由去访问其关联的函数,如果没有的话,自然返回一个错误。
class FlaskBother():
def __init__(self):
self.routes = {}
def route(self,route_str):
def decorator(f):
self.routes[route_str] = f
return f
return decorator
def server(self,path):
view_function = self.routes.get(path)
if view_function:
return view_function()
else:
raise ValueError('Route "{}" has not been registered'.format(path))
这就算完了吗?并没有,让我们尝试运行下面的程序:
app = FlaskBohter()
@app.route("/")
def hello():
return "Hello World"
print app.server("/")
到这里不知道小伙伴们对 @app.route() 有没有一点理解~~如果还没有理解的话,不要急,我们慢慢来,如何将server(path) 挂载到 HTTP 服务器这里就不说了~~好了,小伙伴们下次见~~
欢迎小伙伴们扫码我的头像,关注我的微信号~我是桃子,和有趣的桃子用Python做有趣的事情。