Sanic框架路由用法实例分析


Posted in Python onJuly 16, 2018

本文实例讲述了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框架安装与简单入门》的路由为例:

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参数。如果需要制定一个参数,我们可以使用尖角括号将其括起来,如下所示:

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>。代码如下:

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支持一个可选参数methodsmethods可传入一个列表类型,如此,它将允许处理函数使用列表中的任何HTTP方法。

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,这限制了一条到所提供的主机或主机的路由。

from sanic.response import text
@app.route("/hello/host",host="abc.com")
async def hello_host(request):
  return text("hello host")

在浏览器中访问此路由,如果主机头不匹配abc.com,那么将会报404错误。

路由的装饰器写法除了上面介绍的那种,还可以将其简写,如下所示:

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方法的一个包装器,使用方法如下:

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路径硬编码到你的应用程序当中,这很有用。例如:

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将会是:

/post_handler/laozhang?arg_one=one&arg_two=two

也可以传递多值参数:

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参数来实现:

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,我们可以这样:

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!")

/helloworld都变成了唯一URL。

如果我们只需要部分URL设置成唯一URL,我们可以在@app.route装饰器中传入strict_slashes,并设置为Flase,那么此URL将不是唯一URL。或者我们也可以定义一个蓝图,如下:

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参数到装饰器中来修改它的名称,如下:

from sanic.response import text
@app.route("/get",name="get_info")
async def get(request):
  return text("it is ok!")

此时url_for中传递的将不是函数名称,而是name的值:

print(app.url_for("get_info"))   # /get

同样,也适用于蓝图:

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,此时我们可以这样:

from sanic import Sanic,Blueprint
app = Sanic()
app.static("/home","./static/home.html")

此时我们在访问/home就可以链接到我们指定的HTML中了,此方法同样适用于蓝图。

CompositionView

除了上面那几种定义路由的方法之外,Sanic还提供了CompositionView来动态添加路由:

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类似的修饰符应用于它们。一个典型的用例就是当一些代码想要在处理程序的代码执行之前执行:

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相关内容可查看本站专题:《Python入门与进阶经典教程》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》及《Python文件与目录操作技巧汇总》

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
Python脚本实现DNSPod DNS动态解析域名
Feb 14 Python
python模拟鼠标拖动操作的方法
Mar 11 Python
利用django如何解析用户上传的excel文件
Jul 24 Python
PyTorch上实现卷积神经网络CNN的方法
Apr 28 Python
python自动化报告的输出用例详解
May 30 Python
对python实现合并两个排序链表的方法详解
Jan 23 Python
Pytorch中Tensor与各种图像格式的相互转化详解
Dec 26 Python
python集成开发环境配置(pycharm)
Feb 14 Python
使用Python对Dicom文件进行读取与写入的实现
Apr 20 Python
Python3如何在服务器打印资产信息
Aug 27 Python
Python Pandas 删除列操作
Mar 16 Python
Python可视化神器pyecharts绘制水球图
Jul 07 Python
Sanic框架安装与简单入门示例
Jul 16 #Python
python 除法保留两位小数点的方法
Jul 16 #Python
Python自定义装饰器原理与用法实例分析
Jul 16 #Python
python 正确保留多位小数的实例
Jul 16 #Python
浅谈Python里面小数点精度的控制
Jul 16 #Python
详解Django中间件执行顺序
Jul 16 #Python
转换科学计数法的数值字符串为decimal类型的方法
Jul 16 #Python
You might like
PHP数组循环操作详细介绍 附实例代码
2013/02/03 PHP
php实现微信公众平台发红包功能
2018/06/14 PHP
Prototype 1.5.0_rc1 及 Prototype 1.5.0 Pre0小抄本
2006/09/22 Javascript
类似框架的js代码
2006/11/09 Javascript
用jscript实现列出安装的软件列表
2007/06/18 Javascript
js判断IE浏览器版本过低示例代码
2013/11/22 Javascript
js判断浏览器是否支持html5
2014/08/17 Javascript
jquery实现点击页面计算点击次数
2015/01/23 Javascript
使用jquery+CSS3实现仿windows10开始菜单的下拉导航菜单特效
2015/09/24 Javascript
js数组如何添加json数据及js数组与json的区别
2015/10/27 Javascript
JS中如何比较两个Json对象是否相等实例代码
2016/07/13 Javascript
AngularJS 入门教程之HTML DOM实例详解
2016/07/28 Javascript
jQuery实现二维码扫描功能
2017/01/09 Javascript
vue.js利用defineProperty实现数据的双向绑定
2017/04/28 Javascript
layui.js实现的表单验证功能示例
2017/11/15 Javascript
详解js跨域请求的两种方式,支持post请求
2018/05/05 Javascript
详解extract-text-webpack-plugin 的使用及安装
2018/06/12 Javascript
vue树形结构获取键值的方法示例
2018/06/21 Javascript
Element-ui DatePicker显示周数的方法示例
2019/07/19 Javascript
vue实现购物车小案例
2019/09/27 Javascript
vue使用prop可以渲染但是打印台报错的解决方式
2019/11/13 Javascript
jquery实现加载更多&quot;转圈圈&quot;效果(示例代码)
2020/11/09 jQuery
python通过pil将图片转换成黑白效果的方法
2015/03/16 Python
Python Sql数据库增删改查操作简单封装
2016/04/18 Python
Python实现选择排序
2017/06/04 Python
Python实现1-9数组形成的结果为100的所有运算式的示例
2017/11/03 Python
Python实现爬虫从网络上下载文档的实例代码
2018/06/13 Python
自考毕业自我鉴定范文
2013/10/27 职场文书
社区党员先进事迹
2014/01/22 职场文书
小学数学教研活动总结
2014/07/01 职场文书
大学奖学金获奖感言
2014/08/15 职场文书
六一活动主持词
2015/06/30 职场文书
安全教育培训心得体会
2016/01/15 职场文书
导游词之大雁塔景区
2019/09/17 职场文书
vue-treeselect的基本用法以及解决点击无法出现拉下菜单
2022/04/30 Vue.js
MYSQL事务的隔离级别与MVCC
2022/05/25 MySQL