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中Django框架下的staticfiles使用简介
May 30 Python
Python数据持久化shelve模块用法分析
Jun 29 Python
python pexpect ssh 远程登录服务器的方法
Feb 14 Python
解决python Markdown模块乱码的问题
Feb 14 Python
详解pandas使用drop_duplicates去除DataFrame重复项参数
Aug 01 Python
浅谈python3中input输入的使用
Aug 02 Python
解决python3 安装不了PIL的问题
Aug 16 Python
在Python中获取操作系统的进程信息
Aug 27 Python
Numpy与Pytorch 矩阵操作方式
Dec 27 Python
python实现从ftp服务器下载文件
Mar 03 Python
python 19个值得学习的编程技巧
Aug 15 Python
Python使用socket去实现TCP客户端和TCP服务端
Apr 12 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
德生BCL3000的电路分析和打磨
2021/03/02 无线电
深入PHP magic quotes的详解
2013/06/17 PHP
页面利用渐进式JPEG来提升用户体验度
2014/12/01 PHP
php+curl 发送图片处理代码分享
2015/07/09 PHP
thinkphp自带验证码全面解析
2016/09/18 PHP
thinkPHP多语言切换设置方法详解
2016/11/11 PHP
Thinkphp集成抖音SDK的实现方法
2020/04/28 PHP
js 小贴士一星期合集
2010/04/07 Javascript
js函数模拟显示桌面.scf程序示例
2014/04/20 Javascript
js Dialog 去掉右上角的X关闭功能
2014/04/23 Javascript
get(0).tagName获得作用标签示例代码
2014/10/08 Javascript
jQuery实现分章节锚点“回到顶部”动画特效代码
2015/10/23 Javascript
jQuery元素属性操作实例(设置、获取及删除元素属性)
2016/09/08 Javascript
微信开发之调起摄像头、本地展示图片、上传下载图片实例
2016/12/08 Javascript
JS中如何实现Laravel的route函数详解
2017/02/12 Javascript
Nodejs实现文件上传的示例代码
2017/09/26 NodeJs
Vue项目服务器部署之子目录部署方法
2019/05/12 Javascript
element的el-table中记录滚动条位置的示例代码
2019/11/06 Javascript
用webAPI实现图片放大镜效果
2020/11/23 Javascript
简单了解python模块概念
2018/01/11 Python
python实现自动发送邮件发送多人、群发、多附件的示例
2018/01/23 Python
Python实现替换文件中指定内容的方法
2018/03/19 Python
在CMD命令行中运行python脚本的方法
2018/05/12 Python
python多进程控制学习小结
2018/10/31 Python
python 根据时间来生成唯一的字符串方法
2019/01/14 Python
使用Python Pandas处理亿级数据的方法
2019/06/24 Python
Windows环境下Python3.6.8 importError: DLLload failed:找不到指定的模块
2020/11/01 Python
CSS3 中的@keyframes介绍
2014/09/02 HTML / CSS
Clarks英国官方网站:全球领军鞋履品牌
2016/11/26 全球购物
Vinatis德国:法国领先的葡萄酒邮购公司
2020/09/07 全球购物
简述安装Slackware Linux系统的过程
2012/01/12 面试题
信息技术专业个人自我评价
2013/12/11 职场文书
国贸专业的职业规划书
2014/03/15 职场文书
房屋租赁协议书范本
2014/04/10 职场文书
股东出资证明书范例
2014/10/04 职场文书
2014年乡镇人大工作总结
2014/11/25 职场文书