本文实例讲述了Sanic框架路由用法。分享给大家供大家参考,具体如下:
前面一篇《Sanic框架安装与简单入门》简单介绍了Sanic框架的安装与基本用法,这里进一步学习Sanic框架的路由。
简介
Sanic是一个类似Flask的Python 3.5+ Web服务器,它的写入速度非常快。除了Flask之外,Sanic还支持异步请求处理程序。这意味着你可以使用Python 3.5中新的闪亮的异步/等待语法,使你的代码非阻塞和快速。
前言:Sanic最低支持Python 3.5,如果需要学习Sanic,请先下载版本不低于3.5的Python包
路由
路由允许用户为不同的URL端点指定不同的处理函数,我们取出上一篇《Sanic框架安装与简单入门》的路由为例:
1
2
3
4
5
|
from sanic.response import json
@app .route( "/" )
async def hello_sanic(request):
data = json({ "code" : 0 })
return data
|
当我们在浏览器输入http://localhost:5000/时,根据路由匹配到处理函数hello_sanic
,最终返回JSON对象。Sanic处理函数必须使用语法async def
来定义,因为它们是异步行数。
请求参数
Sanic处理函数带有一个支持请求的参数,即上面的request
参数。如果需要制定一个参数,我们可以使用尖角括号将其括起来,如下所示:
1
2
3
4
|
from sanic.response import json
@app .route( "/hello/<name>" )
async def hello(request,name):
return json({ "name" :name})
|
此时我们再浏览器输入:http://localhost:5000/hello/laowang时,Sanic将会根据路由匹配处理函数,从而返回数据。此时,我们需要对参数进行指定类型,可以在路由中的参数后面加上:type
,假设传入一个age参数,为int类型,路由可以这么写:/hello/<age:int>
。代码如下:
1
2
3
4
|
from sanic.response import json
@app .route( "/hello/<age:int>" )
async def hello_age(request,age):
return json({ "age" :age})
|
此时就可以指定用户传入指定类型的参数了,如果类型不对,将报404错误。
请求类型
对于Sanic处理网络请求,也举了不少例子,可是这些都是GET请求,那我们该如何定义一个POST请求呢?与Flask相同,@app.route
支持一个可选参数methods
,methods
可传入一个列表类型,如此,它将允许处理函数使用列表中的任何HTTP方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
from sanic.response import json
@app .route( "/post/json_data" ,methods = [ "POST" ])
async def post_json(request):
"""
POST请求 json数据
"""
return json(request.json)
@app .route( "/post/form_data" ,methods = [ "POST" ])
async def post_form(request):
"""
POST请求 form表单数据
"""
return json(request.form)
@app .route( "/get/data" ,methods = [ "GET" ])
async def get_data(request):
"""
GET请求
"""
return json(request.args)
|
因为GET请求时默认的,所以,如果需要定义一个GET请求,那么methods参数可以无需传递。@app.route
还支持另一个可选参数host,这限制了一条到所提供的主机或主机的路由。
1
2
3
4
|
from sanic.response import text
@app .route( "/hello/host" ,host = "abc.com" )
async def hello_host(request):
return text( "hello host" )
|
在浏览器中访问此路由,如果主机头不匹配abc.com,那么将会报404错误。
路由的装饰器写法除了上面介绍的那种,还可以将其简写,如下所示:
1
2
3
4
5
6
7
|
from sanic.response import json
@app .get( "/short/get" )
async def short_get(request):
return json(request.args)
@app .post( "/short/post" )
async def short_post(request):
return json(request.json)
|
add_route方法
通常我们指定一个路由,都是通过@app.route
装饰器,然而,这个装饰器实际上只是这个add_route
方法的一个包装器,使用方法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
async def add_get_route(request):
"""
添加GET请求
"""
return json(request.args)
async def add_get_type_route(request,age):
"""
添加带指定类型的参数的GET请求
"""
return json({ "age" :age})
async def add_post_route(request):
"""
添加POST请求
"""
return json(request.json)
app.add_route(add_get_route, "/add_get_route" )
app.add_route(add_get_type_route, "/add_get_type_route/<age:int>" )
app.add_route(add_post_route, "/add_post_route" ,methods = [ "POST" ])
|
重定向
Sanic提供了一个url_for基于处理程序方法名称生成URL的方法。如果你想要避免将URL路径硬编码到你的应用程序当中,这很有用。例如:
1
2
3
4
5
6
7
8
9
10
|
from sanic.response import text,redirect
@app .route( "/url_info" )
async def url_info(request):
url = app.url_for( 'post_handler' ,name = "laozhang" ,arg_one = "one" ,arg_two = "two" )
print (url)
return redirect(url)
@app .route( "/post_handler/<name>" )
async def post_handler(request,name):
print (request.args)
return text( "name:{}" . format (name))
|
url_for使用注意:第一个参数为重定向URL的路由名称(默认为函数名称),并非URL名称。另外我们可以将一些请求参数指派到url_for方法中,上面例子重定向后的url将会是:
1
|
/ post_handler / laozhang?arg_one = one&arg_two = two
|
也可以传递多值参数:
1
2
|
app.url_for( "post_handler" ,favorite = [ "football" , "bastketball" ])
# /post_handler?favorite=football&favorite=bastketball
|
唯一URL
在Flask中,我们顶一个一个URL
为/get
,此时我们访问/get将可以访问成功,如果输入/get/
将会返回404错误,这就是唯一URL。在Sanic中同样拥有此功能,我们可以通过配置strict_slashes
参数来实现:
1
2
3
4
|
from sanic.response import text
@app .route( "/get" ,strict_slashes = True )
async def get(request):
return text( "it is ok!" )
|
注意:strict_slashes
默认值为None,如果不设置的话,访问/get
或/get/
都将可以访问成功,那么这就不是唯一URL了。在上面的例子中,我们将此值设置为True,此时我们输入/get/
,将会返回一个404错误,这样就完成了一个唯一URL的实现。
如果我们需要将所有的URL都设置成为唯一URL,我们可以这样:
1
2
3
4
5
6
7
8
9
|
from sanic import Sanic
from sanic.response import text
app = Sanic(strict_slashes = True )
@app .route( "/hello" )
async def hello(request):
return text( "it is ok!" )
@app .route( "/world" )
async def world(request):
return text( "it is ok!" )
|
/hello
和world
都变成了唯一URL。
如果我们只需要部分URL设置成唯一URL,我们可以在@app.route
装饰器中传入strict_slashes
,并设置为Flase,那么此URL将不是唯一URL。或者我们也可以定义一个蓝图,如下:
1
2
3
4
5
6
|
from sanic import Blueprint
ss_bp = Blueprint( "aaa" ,strict_slashes = False )
@ss_bp .route( "/world" )
async def world(request):
return text( "it is ok!" )
app.blueprint(ss_bp)
|
即使你在app中传递了参数strict_slashes=True
,那么也没有用,所有通过此蓝图定义的URL都将不是唯一URL。
自定义路由名称
通常一个路由的名称为程序处理方法名称,即函数.__name__
生成的,用于可以传递一个name参数到装饰器中来修改它的名称,如下:
1
2
3
4
|
from sanic.response import text
@app .route( "/get" ,name = "get_info" )
async def get(request):
return text( "it is ok!" )
|
此时url_for
中传递的将不是函数名称,而是name的值:
1
|
print (app.url_for( "get_info" )) # /get
|
同样,也适用于蓝图:
1
2
3
4
5
6
7
|
from sanic import Blueprint
ss_bp = Blueprint( "test_bp" )
@ss_bp .route( "/get" ,name = "get_info" )
async def get(request):
return text( "it is ok!" )
app.blueprint(ss_bp)
print (app.url_for( "test_bp.get_info" ))
|
静态文件的URL
我们需要构建一个特定的URL来访问我们需要的HTML,此时我们可以这样:
1
2
3
|
from sanic import Sanic,Blueprint
app = Sanic()
app.static( "/home" , "./static/home.html" )
|
此时我们在访问/home
就可以链接到我们指定的HTML中了,此方法同样适用于蓝图。
CompositionView
除了上面那几种定义路由的方法之外,Sanic还提供了CompositionView
来动态添加路由:
1
2
3
4
5
6
7
8
|
from sanic.views import CompositionView
from sanic.response import text
async def post_handler(request):
print (request.json)
return text( 'it is ok!' )
view = CompositionView()
view.add([ "POST" ],post_handler)
app.add_route(view, "/post_info" )
|
如此,就构造了一个POST请求的接口
处理器装饰器
由于Sanic处理程序是简单的Python函数,因此可以用与Flask类似的修饰符应用于它们。一个典型的用例就是当一些代码想要在处理程序的代码执行之前执行:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
from sanic.response import text
def is_authorized():
return True
def authorized(func):
async def wrapper(request, * args, * * kwargs):
is_auth = is_authorized()
if is_auth:
response = await func(request, * args, * * kwargs)
return response
else :
return text( "it is not authorized" )
return wrapper
@app .route( "/get_user_info" )
@authorized
async def get_user_info(request):
return text( "get_user_info" )
|
希望本文所述对大家Python程序设计有所帮助。
原文链接:https://blog.csdn.net/y472360651/article/details/80138969