【Python】基于FastAPI的Restful规范实践

明月AI 2021-10-28 16:19:04
Python 规范 RESTful 实践 fastapi

以前的Restful规范为何没有持续


我们都知道好的规范是系统可维护性的重要保障,可还是几乎每隔两三年,就得重提一次接口规范。

为什么restful规范难以持续?总结一下,主要原因有:

  1. 规范设计过于复杂:太复杂的规范等于没有;
  2. 人员流动导致规范没有继承:人员流动会导致很多东西都容易断层;
  3. 有规范没工具:这可能是restful主要的问题。每个人都有自己的理解,慢慢的就变了形;
  4. 没有专门的人或者组织持续去推进:特别是人员轮换时,更加明显。

因此,规范的执行需要有保障:

  1. 规范应该尽量保持简单,放弃一些不太重要的细节;
  2. 工具重于规范:结合fastapi设计规范,还会开发一个工具来统一进行规范;
  3. 技术委员会应该持续跟进及监督规范的实施。

接口设计的最高原则:幂等性


接口设计的最高原则是尽量保持幂等性,详见这里

HTTP动词


http的动词有好几个,不过我们只要关注四个即可:

  • GET:获取或者查询数据使用,保持幂等;
  • DELETE:删除数据使用,保持幂等;
  • POST:使用场景通常有两个:
    • 一是增加数据的时候,本身是不幂等的,但是可以通过一些手段来保证重复执行不会产生副作用;
    • 二是做复杂查询时,应该使用POST,而不是用GET。
  • PUT:修改记录使用,保持幂等。

有些使用为了简单,我们把用PUT的地方也用POST,这问题也不大,没必要在这上面过多纠结。

HTTP状态码


常用的HTTP状态码如下:

我们应该尽量使用HTTP状态码来区分接口异常的类型,如果要定义自己的类型,应该使用1000及以后的值。

不要在返回值里,再包含异常的类型了,接口返回值就只是数据本身。

路由命名规范


首先是几个简单的规则:

  1. 路由里不要出现大写字母;
  2. 路由里尽量不要出现下划线,如果确实是两个单词才能描述一个资源,那可以使用连接符(减号);
  3. 路由里通常只有最后一个才可能是动词,前面的应该都是名词。如果使用http的动作词就能表示,则路由中无需动词。

例如:

网上有很多讨论restful规范是用单数还是复数的问题,我觉得没必要在这点上过多纠结。

如果是对单个资源的操作,可以将资源的id直接放到路由中,格式如:

/资源名/{资源id}/{动作}

直接从路由中就能看出,是对什么资源做什么操作。

另外,路由的第一个名词作为模块的名字,在FastAPI中实现为一个子路由(模块)。

输入输出规范


输出数据遵循FastAPI的基本规范:

  • 接口返回值只包含数据,不包含异常状态码;
  • 每一个输入输出的字段都应该定义清楚,包括类型,取值范围,还要有相应的说明;
  • 对于复杂类型,要注意。例如列表,就得定义清楚每个元素的类型,如果是字典,则应该定义成一个单独的结构,定义清楚每个字段的含义。

例如:

class PaddingArgs(BaseModel):
left: float = Field(0.0, title='页面的左边界空白区域', ge=0, lt=0.5,
description='若box的right坐标小于该值与宽度的乘积,则过滤该box')
right: float = Field(0.0, title='页面的右边界空白区域', ge=0, lt=0.5,
description='若box的left坐标大于页面宽度减去该值与宽度的乘积,则过滤该box')
top: float = Field(0.0, title='页面的上边界空白区域', ge=0, lt=0.5,
description='若box的bottom坐标小于该值与高度的乘积,则过滤该box')
bottom: float = Field(0.0, title='页面的下边界空白区域', ge=0, lt=0.5,
description='若box的top坐标大于高度减去该值与高度的乘积,则过滤该box')

在输入输出里通常不要直接使用字典类型,而是应该转换为类似这样的结构。如果在输入参数里,这样定义会变成一个对象。

FastAPI目录规范


FastAPI的项目目录结构:

.
├── app
│ ├── __init__.py
│ ├── readme.md # 接口的描述文档
│ ├── main.py # 主入口文件
│ ├── schema.py # 通用schema
│ ├── settings.py # 配置文件
│ ├── dependencies.py #
│ ├── exceptions.py # 异常相关
│ ├── utile.py # 通用的工具函数
│ ├── common # 公共模块
│ │ ├── __init__.py
│ └── module_name # 模块目录,每个模块独立成一个目录
│ ├── __init__.py
│ ├── router.py # 模块路由文件
│ └── schema.py # 路由文件配置
├── .vscode # vscode配置
│ ├── settings.json
├── .gitignore
├── README.md # 项目说明文档
├── install.md # 安装部署与运维文档
├── Dockerfile # Docker
├── requirements.txt # 项目依赖包

关于项目目录结构,后续我们会有一个FastAPI脚手架去规范,这里要强调一下的是模块目录,我们将模块自身的东西都包含到模块目录中,包括路由文件(有些人喜欢将路由文件放到统一的目录进行管理,不过我觉得这样模块目录就跟别的目录紧耦合在一起了)。

以后我们就可以开发共享一些模块了,例如用户模块,验证码模块等,只要将模块目录放到app目录下,然后在全局入口的main.py中注册相应的路由即可。 网络上的其他资料:

  • http://restful.p2hp.com/
  • 理解Restful:http://www.ruanyifeng.com/blog/2011/09/restful.html
  • Restful设计指南:http://www.ruanyifeng.com/blog/2014/05/restful_api.html
  • 微软Restful API设计指引:https://github.com/Microsoft/api-guidelines/blob/master/Guidelines.md
  • Github Restful API:https://docs.github.com/en/rest/guides/getting-started-with-the-rest-api

本文分享自微信公众号 - 野生AI架构师(Moon-CV) ,作者:明月AI

原文出处及转载信息见文内详细说明,如有侵权,请联系 [email protected] 删除。

原始发表时间: 2021-06-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

版权声明
本文为[明月AI]所创,转载请带上原文链接,感谢
https://cloud.tencent.com/developer/article/1894328

  1. Python Qt GUI设计:QPrinter打印图片类(基础篇—21)
  2. python中一维数组怎么转置
  3. 遇到一个问题,关于Python的复数的
  4. python批量将文件夹里的csv文件转成txt文件
  5. Python 彻底搞懂列表推导式|初级到进阶(实例30+)
  6. python爬虫,遇到urllib.error.URLError: <urlopen error [Errno 11001] getaddrinfo failed>错误
  7. Python程序设计输入五到十之间的整数n,生成并输出一个n位的验证码,不能把大小写字母和数字全写出来
  8. python程序打包之后没运行tkinter
  9. python提取多个Excel文件内目的格内容按一定格式写入新的Excel。
  10. pandas读取csv文件文件末尾都是NaN值,发生了什么?
  11. Python使用matplotlib可视化自定义背景色实战:自定义可视化图像的背景色(Background Color)
  12. 大学生Python实验的列表与元组
  13. python 关于线程的参数args的问题
  14. 如何用python将pdf转成网页html的格式
  15. python基础题 运行后卡在某一步 随后电脑疯狂运转发声 等待无果
  16. 求大神教怎么用python写字
  17. 云计算开发:Python3-expandtabs()方法详解
  18. 9000字深度整理: 全网最详细 Pandas 合并数据集操作总结!
  19. python这个代码有错误,请帮我修改
  20. python redis自带门神 lock 方法
  21. 有关python求众数,中位数和均值的题目
  22. 零基础5天入门Python数据分析:第四课
  23. 零基础5天入门Python数据分析:第三课(上)
  24. 零基础5天入门Python数据分析:第一课
  25. python redis自带门神 lock 方法
  26. 【算法学习】LCP 01. 猜数字(java / c / c++ / python / go)
  27. 【Python量化分析100例】Day2-星期几最容易被割韭菜
  28. python逆推年份,前两问写好了,第三问不会
  29. Python 爬取百度网页如何绕过安全验证
  30. 零基础5天入门Python数据分析:第五课
  31. Python人脸融合时出现关于pybind11的问题
  32. python如何返回除数,公约数,倍数
  33. python 返回多重嵌套列表(多于两层嵌套)的元素
  34. 用Python采集了几千条相亲文案,终于发现了告别单身的秘密
  35. python正负序列题,目前只学到循环,怎么做啊(*꒦ິ⌓꒦ີ)
  36. 拿爱奇艺练手Python爬虫,是在法律边缘试探吗?爬虫技巧学习
  37. Python注释删除代码依然报错
  38. python的pyautogui模块中的pyautogui.scroll()括号中无论写什么值滚动范围都相同
  39. 为什么python在vscode里运行报语法错误,在IDLE里就不会
  40. 请问python如何在将pdf转成word时,去除pdf上的页眉页脚(或者对于每页pdf只取第2行-倒数第二行)
  41. matlab改为python,偏最小二乘回归分析的一个程序
  42. 应该是python基础题希望能用基础方法解决
  43. 想找个会Python的做场外援助,上课没听明白
  44. Python程序,插入不了MySQL的date格式
  45. (初学者)关于Python操作Excel问题
  46. 求人来解答这两道Python题
  47. python中用三引号换行,举例说明
  48. python数码管该怎么用,十四段
  49. python进行中文文本聚类(切词以及Kmeans聚类)
  50. Python - 转换二进制为ASCII码
  51. Python - 在段落中计算令牌
  52. Python - 排序线
  53. Python - 字符串不变性
  54. Python - 文本摘要
  55. Python+微信小程序开发(六)双向绑定和前后端通信
  56. 基于Anaconda搭建Django环境
  57. Django基础篇(2)--视图
  58. 288页的python编程文档,从入门到实践,入门看这一篇就够了
  59. Python Web实战:Flask + Vue 开发一个漂亮的词云网站
  60. 让我深夜十二点催她睡觉,我用 Python 轻松搞定!