Python flask @app.route
转载自 http://python.jobbole.com/80956/
下面是Flask主页给我们的第一个例子,我们现在就由它入手,深入理解“@app.route()”是如何工作的。
Python
| 
 1 
2 
3 
4 
5 
 | 
 app = Flask(__name__) 
@app.route("/") 
def hello(): 
    return "Hello World!" 
 | 
@app.route和其它装饰器
要想明白“@app.route()”的工作原理,我们首先需要看一看Python中的装饰器(就是以“@”开头的那玩意,下面接着函数定义)。
究竟什么是装饰器?没啥特别的。装饰器只是一种接受函数(就是那个你用“@”符号装饰的函数)的函数,并返回一个新的函数。
当你装饰一个函数,意味着你告诉Python调用的是那个由你的装饰器返回的新函数,而不仅仅是直接返回原函数体的执行结果。
还不是很明白?这里是一个简单的例子:
Python
| 
 1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
 | 
 # This is our decorator 
def simple_decorator(f): 
    # This is the new function we're going to return 
    # This function will be used in place of our original definition 
    def wrapper(): 
        print "Entering Function" 
        f() 
        print "Exited Function" 
    return wrapper 
@simple_decorator  
def hello(): 
    print "Hello World" 
hello() 
 | 
运行上述代码会输出以下结果:
Entering Function
Hello World
Exited Function
很好!
现在我们有点明白怎样创建我们自己的“@app.route()”装饰器了,但你可能会注意到有一个不同点,就是我们的simple_decorator不可以接受任何参数, 但“@app.route()”却可以。
那么我们怎样才能给我们的装饰器传参数?要实现这个我们只需创建一个“decorator_factory”函数,我们调用这个函数,返回适用于我们函数的装饰器。现在看看如果实现它。
Python
| 
 1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
 | 
 def decorator_factory(enter_message, exit_message): 
    # We're going to return this decorator 
    def simple_decorator(f): 
        def wrapper(): 
            print enter_message 
            f() 
            print exit_message 
        return wrapper 
    return simple_decorator 
@decorator_factory("Start", "End") 
def hello(): 
    print "Hello World" 
hello() 
 | 
给我们的输出是:请注意在我们写@decorator_factory(“Start”, “End”)时,我们实际调用的是decorator_factory函数,实际返回的装饰器已经被用上了,代码很整洁,对吧?
Start
Hello World
End
把“app”放进“app.route”
现在我们掌握了装饰器怎样工作的全部前置知识 ,可以重新实现Flask API的这个部分了,那么把我们的目光转移到“app”在我们Flask应用中的重要地位上面来。
在开始解释Flask对象里面发生了什么之前,我们先创建我们自己的Python类NotFlask。
Python
| 
 1 
2 
3 
4 
 | 
 class NotFlask(): 
    pass 
app = NotFlask() 
 | 
这不是个很有趣的类,不过有一样值得注意,就是这个类的方法也可以被用作装饰器,所以让我们把这个类写得更有趣一点,加一个称作 route的方法,它是一个简单的装饰器工厂。
Python
| 
 1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
 | 
 class NotFlask(): 
    def route(self, route_str): 
        def decorator(f): 
            return f 
        return decorator 
app = NotFlask() 
@app.route("/") 
def hello(): 
    return "Hello World!" 
 | 
这个装饰器和我们之前创建的那些最大的不同,在于我们不想修改被我们装饰的函数的行为,我们只是想获得它的引用。
所以,最后一步是我们打算去利用一个特性,就是用装饰器函数的副产品去保存一个提供给我们的路径之间的链接,装饰器函数应该与它关联起来。
为了实现这个,我们给我们的NotFlask对象加一个“routes”字典,当我们的“decorator”函数被调用,路径将被插入新字典中函数对应的位置。
Python
| 
 1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
 | 
 class NotFlask(): 
    def __init__(self): 
        self.routes = {} 
    def route(self, route_str): 
        def decorator(f): 
            self.routes[route_str] = f 
            return f 
        return decorator 
app = NotFlask() 
@app.route("/") 
def hello(): 
    return "Hello World!" 
 | 
现在我们就要完成了!可如果没法访问内部的视图函数,保存路径的字典又有什么用?让我们加入一个方法serve(path),当给定的路径存在时运行一个函数并给们我结果,当路径尚未注册时则抛出一个异常。
Python
| 
 1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
 | 
 class NotFlask(): 
    def __init__(self): 
        self.routes = {} 
    def route(self, route_str): 
        def decorator(f): 
            self.routes[route_str] = f 
            return f 
        return decorator 
    def serve(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 = NotFlask() 
@app.route("/") 
def hello(): 
    return "Hello World!" 
 | 
在这个系列我们只关注重现那些热门库提供的友好API,所以钩挂“serve”方法实现一个HTTP服务器其实有一点超出本文的范围,当然结果是确定的,运行下述片段:
Python
| 
 1 
2 
3 
4 
5 
6 
7 
 | 
 app = NotFlask() 
@app.route("/") 
def hello(): 
    return "Hello World!" 
print app.serve("/") 
 | 
我们会看到:
Hello World!
我们已经完成了一个的Flask网页上第一个例子的非常简单的重现,让我们写一些快速测试检测我们简单重现的Flask的“@app.route()”是否正确。
Python
| 
 1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
 | 
 class TestNotFlask(unittest.TestCase): 
    def setUp(self): 
        self.app = NotFlask() 
    def test_valid_route(self): 
        @self.app.route('/') 
        def index(): 
            return 'Hello World' 
        self.assertEqual(self.app.serve('/'), 'Hello World') 
    def test_invalid_route(self): 
        with self.assertRaises(ValueError): 
            self.app.serve('/invalid') 
 | 
吸口气。
完全正确!所以,仅仅是一个简单的包含一个字典的装饰器, 就重现了Flask的“app.route()”装饰器的基本的行为。
在本系列的下一篇,也是Flask的app.route()的最后一篇,将通过解析下面这个例子来解释动态URL模式是如何工作。
Python
| 
 1 
2 
3 
4 
5 
 | 
 ; html-script: false ]app = Flask(__name__) 
@app.route("/hello/<username>") 
def hello_user(username): 
    return "Hello {} !".format(username) 
 | 
Python flask @app.route的更多相关文章
- Python Flask 开发学习笔记
		
Flask学习 安装pipenv虚拟环境 pip Install pipenv 运行pipenv pipenv --version 进入虚拟容器 pipenv install 安装flask pipe ...
 - Flask从入门到放弃1:路由app.route()
		
Flask从入门到放弃1: Flask中的路由app.route(): 参考来源:http://python.jobbole.com/80956/ https://www.raspberrypi.or ...
 - Python Flask 在Sina App Engine (SAE)上安家
		
早就听说了Python的大名,随着的编程语言的理解加深,越发认为动态语言的威力--真大呀. 趁这段时间不忙,我也用Python写了一个应用,而且将其部署到Sina App Engine (SAE).S ...
 - Flask - app.debug=True,python manage.py和export FLASK_DEBUG=True,flask run的不同。
		
TL;DR,可以直接看下面的总结 问题1:为什么app.config['DEBUG'] = True,然后flask run并没有开启debugger和reloading,而直接运行脚本(python ...
 - 【Azure 应用服务】Python flask 应用部署在Aure App Service 遇见的 3 个问题
		
在App Service(Windows)中部署Flask应用时的注意事项: ● 添加Python扩展插件,Python 3.6.4 x64: ●● 配置 FastCGI 处理程序,添加Web.con ...
 - 【Azure 应用服务】Python flask 应用部署在Aure App Service中作为一个子项目时,解决遇见的404 Not Found问题
		
问题描述 在成功的部署Python flask应用到App Service (Windows)后,如果需要把当前项目(如:hiflask)作为一个子项目(子站点),把web.config文件从wwwr ...
 - 【Azure 应用服务】Azure App Service For Linux 上实现 Python Flask Web Socket 项目 Http/Https
		
问题描述 在上篇博文"[Azure 应用服务]App Service for Linux 中实现 WebSocket 功能 (Python SocketIO)"中,实现了通过 HT ...
 - python flask route中装饰器的使用
		
问题:route中的装饰器为什么感觉和平时使用的不太一样,装饰器带参数和不太参数有什么区别?被修饰的函数带参数和不带参数有什么区别? 测试1:装饰器不带参数,被修饰的函数也不带参数. def log( ...
 - Flask系列03--Flask的路由 app.route中的参数, 动态参数路由
		
Flask–路由 添加路由的两种方式 第一种 @app.route("/my_de") def detail() 第二种(了解即可) app.add_url_rule(" ...
 
随机推荐
- 使用EXtjs6.2构建web项目
			
一.项目简介 众所周知ext是一款非常强大的表格控件,尤其是里边的grid为用户提供了非常多的功能,现在主流的还是用extjs4.0-4.2,但是更高一点的版本更加符合人的审美要求.因此,在今天咱们构 ...
 - NC 销售订单
			
主表:so_sale,主键:csaleid 子表1:so_saleorder_b 主键:corder_bid 子表2:so_saleexecute 主键:csale_bid 要求子表1和子表2 主键相 ...
 - 记录PHP的超全局变量$_SERVER
			
$_SERVER是PHP中十分实用的超全局变量,在开发可移植的网站的时候会变得很有用. 下面我记录一下我自己常用到的几个变量 1.$_SERVER['SERVER_NAME']:记录了网站的域名. 2 ...
 - centos 6.5 redis 安装
			
安装教程有用的地址 https://my.oschina.net/u/2478188/blog/726984: 错误1 Redis: You need tcl 8.5 or newer in orde ...
 - Oracle11g字符集AL32UTF8修改为ZHS16GBK详解
			
此问题发生在数据库迁移过程中.源数据库:自己笔记本上win7 64位系统的oracle11g个人版,字符集ZHS16GBK :目标数据库,HP的sqlserver2008 系统 64位数据库服务器,字 ...
 - Python的多线程(threading)与多进程(multiprocessing )
			
进程:程序的一次执行(程序载入内存,系统分配资源运行).每个进程有自己的内存空间,数据栈等,进程之间可以进行通讯,但是不能共享信息. 线程:所有的线程运行在同一个进程中,共享相同的运行环境.每个独立的 ...
 - Python Numpy,Pandas基础笔记
			
Numpy Numpy是python的一个库.支持维度数组与矩阵计算并提供大量的数学函数库. arr = np.array([[1.2,1.3,1.4],[1.5,1.6,1.7]])#创建ndarr ...
 - SQL语句
			
数据查询:SELECT 以下所有的查询都基于以下的表格: 学生表:STUDENT(SNO,Sname,ssex,sage,sdept); 课程表:course(cno,cnama,cpno,ccred ...
 - Asp.net MVC的ViewData与ViewBag以及TemplateData的使用与区别
			
ViewData ViewBag 它是Key/Value字典集合 它是dynamic类型对像 从Asp.net MVC 1 就有了 ASP.NET MVC3 才有 基于Asp.net 3.5 fram ...
 - iOS 开发总结(下)
			
来源:蝴蝶之梦天使 链接:http://www.jianshu.com/p/d333cf6ae4b0 四十.AFNetworking 传送 form-data 将JSON的数据,转化为NSData, ...