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中的try和finally和with方法
May 05 Python
Python缩进和冒号详解
Jun 01 Python
Python使用cookielib模块操作cookie的实例教程
Jul 12 Python
基于Python Numpy的数组array和矩阵matrix详解
Apr 04 Python
Python批量发送post请求的实现代码
May 05 Python
Python解析并读取PDF文件内容的方法
May 08 Python
Python常见数据类型转换操作示例
May 08 Python
python地震数据可视化详解
Jun 18 Python
Pandas之MultiIndex对象的示例详解
Jun 25 Python
python3获取当前目录的实现方法
Jul 29 Python
python实现人机猜拳小游戏
Feb 03 Python
python使用html2text库实现从HTML转markdown的方法详解
Feb 21 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 gd2 上传图片/文字水印/图片水印/等比例缩略图/实现代码
2010/05/15 PHP
php警告Creating default object from empty value 问题的解决方法
2014/04/02 PHP
Yii框架在页面输出执行sql语句以方便调试的实现方法
2014/12/24 PHP
PHP常用操作类之通信数据封装类的实现
2017/07/16 PHP
在Ubuntu 18.04上安装PHP 7.3 7.2和7.0的方法
2019/04/09 PHP
精通JavaScript 纠正 cleanWhitespace函数
2010/03/11 Javascript
利用jQuery插件扩展识别浏览器内核与外壳的类型和版本的实现代码
2011/10/22 Javascript
javascript返回顶部效果(自写代码)
2013/01/06 Javascript
js对table的td进行相同内容合并示例详解
2013/12/27 Javascript
SeaJS入门教程系列之完整示例(三)
2014/03/03 Javascript
Nodejs实现的一个简单udp广播服务器、客户端
2014/09/25 NodeJs
javascript事件冒泡和事件捕获详解
2015/05/26 Javascript
JS实现日期时间动态显示的方法
2015/12/07 Javascript
JS获取checkbox的个数简单实例
2016/08/19 Javascript
js控制文本框只能输入中文、英文、数字与指定特殊符号的实现代码
2016/09/09 Javascript
form表单序列化详解(推荐)
2017/08/15 Javascript
Vue2.0 给Tab标签页和页面切换过渡添加样式的方法
2018/03/13 Javascript
js构造函数constructor和原型prototype原理与用法实例分析
2020/03/02 Javascript
Vue-resource安装过程及使用方法解析
2020/07/21 Javascript
vue-cli4使用全局less文件中的变量配置操作
2020/10/21 Javascript
[48:30]LGD vs infamous Supermajor小组赛D组 BO3 第一场 6.3
2018/06/04 DOTA
Python如何判断数独是否合法
2016/09/08 Python
Django的HttpRequest和HttpResponse对象详解
2018/01/26 Python
基于Python实现用户管理系统
2019/02/26 Python
python字符串替换第一个字符串的方法
2019/06/26 Python
pandas.DataFrame的pivot()和unstack()实现行转列
2019/07/06 Python
Python3变量与基本数据类型用法实例分析
2020/02/14 Python
Django封装交互接口代码
2020/07/12 Python
Python从MySQL数据库中面抽取试题,生成试卷
2021/01/14 Python
介绍一下gcc特性
2012/01/20 面试题
外语学院毕业生的自我鉴定
2013/11/28 职场文书
千元咖啡店的创业计划书范文
2013/12/29 职场文书
银行给客户的感谢信
2015/01/23 职场文书
病人写给医生的感谢信
2015/01/23 职场文书
浅谈由position属性引申的css进阶讨论
2021/05/25 HTML / CSS
Tomcat配置访问日志和线程数
2022/05/06 Servers