Web开发之旅–使用Flask 实现REST架构的API
原创: 程序猿与吉他狗 程序猿与吉他狗 2018-10-22
https://mp.weixin.qq.com/s/dowlEqAWN9v9SD_Y2-eoKA
最近几年移动互联网的高速发展,业务逻辑被越来越多的迁移到客户端一侧,例如iOS和Android的各种App,服务器的主要功能(有时是唯一功能)是为客户端提供数据存取服务。在这种模式中,服务器变成了Web 服务或应用编程接口(Application Programming Interface,API)。Flask 是开发REST 架构Web 服务的理想框架,因为Flask 天生轻量。下面我们就来看看如何使用Flask实现API。

一、为什么要使用RESTful-API?

关于REST架构的相关很多细节可以参考书籍《RESTful Web Services Cookbook》,这本书详尽的介绍了实现REST架构的相关细节,REST的英文是representational state transfer(表现性状态转移),从字面理解就是将资源的呈现任务转移到前端,服务器后端只负责提供资源就行了,我们不需要再写模板,考虑前端呈现了,只需要把数据返回给前端,由前端自行处理就行了,REST中一个非常关键的特点就是无状态,例如我们不知道当前用户是否已经登录,不能使用上下文来实现用户状态的存储,每一个到来的请求服务器都认为是毫无关联的,这样也带来了更大的好处就是前后端完全解耦,对于弹性扩容提供了便利。RESTful-API还有一个好处就是区分版本,可以实现在不影响老版本用户的情况升级新的功能。使用Flask实现RESTful-API有很多种方式,既可以手动实现也可以使用Flask-restful扩展来实现,为了便于理解,本文主要通过手动实现,理解原理后使用扩展实现就很简单,看官方文档就可以搞定了。

二、资源定位及请求方法

前面讲到后端服务器实际只是为前端提供资源,那么后端的核心就是资源,什么是资源呢?例如前面实现的文章、用户等等存储在数据库中的内容,对数据库的操作有增删改查这四种方法,简称为CRUD,其实Http请求同样有方法与之对应,只是我们平时就用了GET和POST两种,那对应的方法分别是什么呢?

这里尤其要关注状态码,不要在资源不存在的时候返回200,而是应该返回404,用户权限不够的时候应该返回403等等,这个和我们前面的方法有很大区别,前面为了使用户体验更好,即使访问出错了,用户浏览器也能收到错误的信息,页面显示仍然正常。

REST架构的提出者Roy Fielding正是Http协议的主要设计者,他认为现在的网络服务存在很大的问题,明明我为你们设计了那么多的请求方法,结果你们删除资源都是用GET方法,完全背离了设计初衷,但是广大程序猿都是怎么好用怎么来,所以他在2000年的博士论文中提出了REST架构,我们来看看REST和我们之前使用的方法的资源定位的区别:


这样一对比以后是不是感觉瞬间清爽了,通过不同的请求方法来区分对资源不同的操作。

三、请求和响应的body

前面有两篇文章详细的讲了请求和响应,传统方法后端返回的是html文件,使用REST架构可选用JSON和XML,但是JSON和JavaScript 联系紧密,现在前端使用JavaScript实现的框架层出不穷,所以使用JSON来传递数据成为了首选方式,这里的响应内容和传统的有很大区别,因为请求是无状态的,例如分页查询的时候我们并不知道这个请求之前请求的是哪一页,所以在响应的时候要将下一页和上一页的URL返回。下面讲解具体如何实现RESTful-API。

四、具体实现

(一)创建蓝本和错误处理

前面我们创建过auth、blog、main这三个蓝本,这里的创建方法相同:

api_v1这里的v1是用来区分版本,如果后续功能发生变化,就可以新建一个v2的蓝本实现兼容。

app/api_v1/init.py:

app/init.py:在create_app工厂函数中注册

app/api_v1/errors.py:用于处理错误

app/main/errors.py:这个是之前用于处理错误的文件,但是加入api后会导致api接收的错误信息无法识别,所以也需要修改,思路就是识别请求头中的accpet_mimetypes,如果是json就返回json格式的响应。

(二)用户认证

用户认证因为REST架构请求无状态了,服务器无法记住客户端的任何信息,所以每次请求都必须携带认证信息,传统的认证方式服务器会把用户的认证信息存在会话中,不需要每次请求都携带认证信息,这里REST架构和传统方式的区别很大。

REST发送用户名密码不是通过POST表单的方式,而是将认证信息放在请求头的Authorization中,虽然我们可以自行实现,但是有已有的库对这些细节操作进行了封装,这里就使用flask-HTTPAuth来进行认证。

$pip install flask-httpauth

app/api_v1/authentication.py:

这个文件的内容稍微有点复杂,下面逐个进行解释:

先将HTTPBasicAuth类进行实例化,后面会用到它的3个装饰器,auth.verify_password:用来验证请求头中的认证信息是否正确,这里有两种认证方式,一是传统的账号密码,二是令牌方式。

auth.login_required:类似于Flask-login中的login_required来实现路由的保护,api.before_request这个装饰器是api这个蓝本的请求钩子,也就是请求这个蓝本下所有路由都需要先经过它来处理。

auth.error_handler:当认证发生错误时,由它来处理。

get_token这个视图函数是当用户认证成功后,可以通过它来获得令牌方便后续的访问,也就是后续请求只需要携带令牌就可以了,不需要每次都使用用户名和密码,因为令牌有过期时间,这样安全性更好一点,当然问题的关键还是要使用https来确保传递过程中不被攻击者轻易获取。

在verify_password中使用了User模型类的静态方法verigy_auth_token和实例方法generate_auth_token,这个是用来识别令牌是否有效以及这个令牌来自哪个用户的和为用户生成令牌。所以在models.py中的User类中需要添加这部分内容:

这样就实现了API的认证,访问权限的控制和传统方式一样,使用自行编写的装饰器来实现即可。

vv/app/api_v1/decorators.py:

在视图函数前使用这个装饰器就可以实现权限控制了。

(三)资源序列化及路由视图

flask-restful扩展库对这一块封装的很好,接下来我们手动实现资源的序列化,但是不推荐手动实现,这样会导致代码冗余和逻辑混乱,这里实现只是为了讲解原理。资源序列化简单的理解就是把资源包装成JSON数据返回给前端,如果手动实现的话,需要构造一个字典,把返回的内容以键值对的形式放入字典中,然后使用jsonify把字典转换成JSON格式。下面以posts这个资源为例:

vv/app/api_v1/posts.py:

通过id查询数据库,然后把查询结果使用to_json转换成字典,最后通过jsonify把字典返回,这个to_json是在模型中实现的,在models.py中的Post类添加该方法。


当查询全部post的时候由于数量较大,需要使用分页查询。

vv/app/api_v1/posts.py:

因为无状态的原因,这里需要将上一页和下一页的地址都返回给前端。

新建文章的方法:

vv/app/api_v1/posts.py:

这里使用了Post类的静态方法from_json来创建post实例,返回的时候把新建的结果返回给前端,且状态码为201,表示创建成功。下面实现models.py中Post类的from_json方法:

这里用到了自定义的异常,在app文件夹下新建一个exceptions.py:

最后就是修改文章的实现方法:

通过id查询到该文章,然后判断权限,修改post的属性,提交数据库,最后返回该文章。

本文简单的介绍了Flask实现RESTful-API的方法,设计一个良好的API还有很多的内容,这里就不再展开,因为它们与框架甚至是语言都无关的,有兴趣的朋友可以看看《RESTful Web Services Cookbook》,貌似全平台缺货,我有一个不太清晰的电子版,需要的可以留言。

Web开发之旅--使用Flask 实现REST架构的API相关推荐

  1. WEB开发中,使用JSON-RPC好,还是RESTful API好?

    看到知乎上有这样一个问题 WEB开发中,使用JSON-RPC好,还是RESTful API好? 还有其他优秀的推荐方案吗? -------------------------------------- ...

  2. Web开发day1:使用flask快速搭建网站

    目录 1. 简单跑通 2. 浏览器能识别的标签 2.1 编码(head中) 2.2 标题(head中) 2.3 标题(body中,块级标签) 2.4 div和span(body中,div块级标签,sp ...

  3. java的web开发之旅——第3站javascript

    js 1. javaScript 1.1 js是什么 1.2 js的语言特征 1.3 js的组成 1.4 js的引入 1.4.1 内部引用 1.4.2 外部引用 1.4.3 script标签规范化 2 ...

  4. pythonweb开发-Python Web开发从入门到精通

    Python Web开发从入门到精通循序渐进地讲解了Python Web开发的核心知识,并通过具体实例的实现过程演示了Web开发程序的流程.Python Web开发从入门到精通共15章,内容包括Pyt ...

  5. python web 开发教程下载_Python Web开发从入门到精通

    Python Web开发从入门到精通循序渐进地讲解了Python Web开发的核心知识,并通过具体实例的实现过程演示了Web开发程序的流程.Python Web开发从入门到精通共15章,内容包括Pyt ...

  6. python web开发-Python Web开发从入门到精通

    Python Web开发从入门到精通循序渐进地讲解了Python Web开发的核心知识,并通过具体实例的实现过程演示了Web开发程序的流程.Python Web开发从入门到精通共15章,内容包括Pyt ...

  7. python岗位任职要求-2020 python web开发就业要求锦集

    郑州 Python程序员 河南三融云合信息技术有限公司 6-8k·12薪 7个工作日内反馈 郑州 1个月前 本科及以上2年以上语言不限年龄不限 微信扫码分享 收藏 Python程序员 河南三融云合信息 ...

  8. 开发db文件_Swoole高效跟传统的web开发有什么区别?life

    一.swoole的运行模式 Swoole高效跟传统的web开发有什么区别,除了传统的LAMP/LNMP同步开发模式,swoole的异步开发模式是怎么样的. 我的官方群点击此处.获取更多的swoole学 ...

  9. Web开发与设计之Google兵器谱-Web开发与设计利器

    Google 的使命是 Web,在 Google 眼中,未来的一切应用都将 Web 化,一直以来,Google 为 Web 开发与设计者推出了大量免费工具,让他们更好地创建,维护,改善他们的 Web ...

  10. 移动web开发rem+js适配布局开发

    浏览器现状 pc端浏览器  360浏览器,谷歌浏览器,qq浏览器百度浏览器,搜狗浏览器.IE浏览器 移动端常见浏览器  uc浏览器 qq浏览器 欧朋浏览器 百度手机浏览器,360安全浏览器... 国内 ...

最新文章

  1. 汉诺塔(三)_栈的应用
  2. MyBatis学习笔记(一)
  3. maven-compiler-plugin
  4. Linux 下如何查找 MySQL 数据库的数据根目录呢?
  5. Python库glob作用分析
  6. JSW Java_java服务安装(一):使用java service wrapper及maven打zip包
  7. 地方命令SqlServer2008中解决在表上点右键把【编辑前200行】变成【编辑前10000行】的方法!...
  8. 在Jupyter Notebook中实现图像检测服务的调用
  9. ElasticSearch6.8.1集群搭建及Java客户端编写
  10. activiti 启动tomcat乱码_Activiti 流程图片显示乱码问题分析与解决
  11. 为什么建网站需要服务器,建网站需不需要服务器
  12. 职称英语计算机考试取消,2020年职称英语考试取消了吗
  13. 【Flutter小记3】Android打开前置或广角摄像头的同时打开闪光灯方案
  14. 见信如晤::‘卷福’读信:我全心全意去拥抱您
  15. 数字图像处理(入门篇)十四 透视变换
  16. 【学堂上新】Unity UGUI 渲染 3D 对象详解
  17. 解决:java.sql.SQLException:Value ‘0000-00-00‘ can not be represented as java.sql.Date
  18. 安卓桌面整理app_想让你的桌面变得整洁干净,这几款桌面整理软件别错过
  19. 在router中使用pinia报错解决
  20. Android集成QQ登录

热门文章

  1. JavaScript控制类名(className属性)
  2. HDU 4031 Attack
  3. HTML5的WebGL实现的3D和2D拓扑树
  4. SAP BW 例程(Routine)【开始例程、关键值或特性的例程、结束例程】
  5. Ubuntu 12.04下Proftpd FTP服务器配置
  6. 论文阅读笔记——人脸网络:人脸识别和聚类的统一嵌入
  7. Python数据预处理之清及
  8. spring配置jackson不返回null值
  9. Android:使用GsonFormat插件遇到的坑
  10. 2016项目经验总结