最近想搞一下接口, 希望能简单上手, 前后端分离, 大致看了一遍 SpringBoot, Gin, NodeJs, Flask, Django, FastAPI 等, 感觉还是用 Python 语言来写比较简单呀, 关键点在于它语法清晰, 能让我直接思考业务逻辑, 而不是各种语法折腾.

FASTAPI 简介

Documentation: https://fastapi.tiangolo.com

Source Code: https://github.com/tiangolo/fastapi


FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.8+ based on standard Python type hints.

The key features are:

  • Fast: Very high performance, on par with NodeJS and Go (thanks to Starlette and Pydantic). One of the fastest Python frameworks available.
  • Fast to code: Increase the speed to develop features by about 200% to 300%. *
  • Fewer bugs: Reduce about 40% of human (developer) induced errors. *
  • Intuitive: Great editor support. Completion everywhere. Less time debugging.
  • Easy: Designed to be easy to use and learn. Less time reading docs.
  • Short: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
  • Robust: Get production-ready code. With automatic interactive documentation.
  • Standards-based: Based on (and fully compatible with) the open standards for APIs: OpenAPI (previously known as Swagger) and JSON Schema.

总结这个 fastapi 框架的特点就是, 运行快, 体量小, BUG少, 代码量少, 自动生成交互文档 很适合写后端接口.

我觉得它和 flask / django 的最大的优势在于利用了 Python3.6+ 的类型验证, 数据校验 ( pydantic 库) 等这样极大地减少了编写各种参数校验等的类重复性代码吧.

项目结构

主要来自慕课网的学习公开课笔记, 目录结构如下:

base

  • __ init __.py
  • base_01.py
  • base_02.py
  • base_03.py
  • base_04.py
  • ...

main.py

其中 main.py 的内容如下:

from fastapi import FastAPI
import uvicorn from base import app01
from base import app02
from base import app03
from base import app04 app = FastAPI(
title="FastAPI 基础教程",
version='1.0.0',
docs_url='/docs'
) app.include_router(app01, prefix='/app01', tags=['请求参数和验证'])
app.include_router(app02, prefix='/app02', tags=['响应处理和配置'])
app.include_router(app03, prefix='/app03', tags=['依赖注入和系统'])
app.include_router(app04, prefix='/app04', tags=['安全认证和授权']) if __name__ == '__main__':
uvicorn.run('main:app', host='0.0.0.0', port=8000, reload=True, workers=1)

请求参数与验证

关于前端浏览器向后端发送请求, 请求地址一般都会涉及路径参数查询参数

  • 无参数: /path
  • 路径参数: /path/
  • 查询参数: /path?name=youge

一下演示的案例都写在 base_01.py 这个子路由里面:

from fastapi import APIRouter, Path, Query, Cookie, Header
from enum import Enum
from typing import Optional, List
from pydantic import BaseModel, Field
from datetime import date app01 = APIRouter() ....

无请求参数

@app01.get("/path/parameters")
def path_params01():
return { 'msg': 'hello, world!' }
http://127.0.0.1:8000/app01/path/parameters

路径参数

# 请求参数是后面带 /xxx 路径的, 参数和处理函数一致, 且函数顺序就是路由的顺序

@app01.get("/path/{parameters}")
def path_params01(parameters: str):
return { 'msg': parameters }
http://127.0.0.1:8000/app01/path/admin

此例接口的 admin 是一个路径参数变量, 写啥返回啥

请求参数

# 请求参数就是后面带 ? 的, 参数和处理函数一致

@app01.get("/path/parameters")
def path_params01(parameters: str):
return { 'msg': parameters }
http://127.0.0.1:8000/app01/path/parameters?parameters=youge

枚举参数

# 枚举类
class CityName(str, Enum):
Beijing = "Beijing China"
ShangHai = "ShangHai China" # 枚举参数类型
@app01.get("/enum/{city}")
async def latest(city: CityName):
if city == CityName.Beijing:
return { 'cityName': city, 'confirmed': 999, 'death': 10 } if city == CityName.ShangHai:
return { 'cityName': city, 'confirmed': 666, 'death': 6 } return { 'cityName': city, "latest": 'unknow'}
http://127.0.0.1:8000/app01/enum/ShangHai%20China

这里的 city 路径变量是一个枚举的, 要么是 Beijing, 要么是 Shanghai, 否则就没法处理啦.

文件参数

# 文件参数类型 path
@app01.get('files/{file_path: path}')
def file_path(file_path: str):
return f"The file path is {file_path}"

例如我们要上传的的文件路径是: C:\user\Desktop\test.xlsx

http://127.0.0.1:8000/app01files/{file_path: path}?file_path=C%3A%5Cuser%5CDesktop%5Ctest.xlsx

则响应为:

"The file path is C:\\user\\Desktop\\test.xlsx"

参数验证-数字

# 长度和正则表达式的验证, 路径参数

@app01.get("/path_/{age}")
def path_params_validate(
num: int = Path(..., ge=0, le=100, title='your age', description='您的年龄')
):
return num
http://127.0.0.1:8000/app01/path_/20

这里要传的路径参数 age, 要求是一个 int 类型, 必填, 值在 0 ~ 100 之间, 含义是 "您的年龄".

如果说传递了一个 200, 则返回的异常响应是 (postman 测):

{
"detail": [
{
"type": "less_than_equal",
"loc": [
"path",
"age"
],
"msg": "Input should be less than or equal to 100",
"input": "200",
"ctx": {
"le": 100
},
"url": "https://errors.pydantic.dev/2.4/v/less_than_equal"
}
]
}

参数验证-选填与必填

# 给了默认值就是选填参数, 否则为必填参数

@app01.get('/query')
def page_limit(page: int = 1, limit: Optional[int] = None):
if limit:
return { 'page': page, 'limit': limit }
return { 'page': page }
http://127.0.0.1:8000/app01/query?page=10&limit=100

这里的查询参数 page: int = 1 给了默认值 1 则表明为前端选传, 如果是 page: int 则为必传.

参数验证-Bool 值转换

#  查询参数 bool 值的转换

@app01.get("/query/bool/conversion")
def type_conversion(param: bool = False):
return param
http://127.0.0.1:8000/app01/query?page=10&limit=100

参数验证 - 多参数列表

# 多个查询参数的列表, 列表别名, 前端正则校验等

@app01.get("/query/validations")
def query_params_validate(
value: str = Query(..., min_length=8, max_length=16, regex='^a'),
values: List[str] = Query(default=['v1', 'v2'], alias='alias_name')
):
return value, values

此接口表示要传两个查询参数 valuevalues

  • value: 字符类型, 必传, 长度在 8 ~ 16 之间, 以 "a" 开头
  • values: 列表类型, 里面的元素是字符类型, 默认值是 "v1", "v1", 别名是 "alias_name"
http://127.0.0.1:8000/app01/query/validations?value=admin123&alias_name=cj&alias_name=youge&alias_name=18

响应:

{
"data": {
"value": "admin123",
"values": [
"cj",
"youge",
"18"
]
}
}

参数验证 - Body 多参数混合

先建一个模型类:

# 请求体多参数混合

class CityInfo(BaseModel):
name: str = Field(..., example='Beijing')
country: str
country_code: str = None
country_population: int = Field(default=800, ge=800,
title='人口数量', description='国家人口数量')
@app01.post("/request_body/city")
def city_info(city: CityInfo):
print(city.name, city.country)
return city

这样之间就可以通过属性的方式对模型类进行访问.

请求体:

curl -X 'POST' \
'http://127.0.0.1:8000/app01/request_body/city' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"name": "Beijing",
"country": "china",
"country_code": "cn001",
"country_population": 800
}'

响应体:

{
"name": "Beijing",
"country": "string",
"country_code": null,
"country_population": 800
}

也是可以进行混合的验证

# 混合
@app01.put("/request_body/city/{name}")
def mix_city_info(
name: str,
city01: CityInfo,
city02: CityInfo,
confirmed: int = Query(ge=0, description='确诊数', default=0),
death: int = Query(ge=0, description='死亡数', default=0)
):
if name == 'Shanghai':
return { 'Shanghai': { 'confirmed': confirmed, 'death': death } }
return city01, city02

用 postman 测试一下 post 请求如下:

参数验证 - 请求体嵌套

class Data(BaseModel):
city: List[CityInfo] = None
date: date
confirmed: int = Field(ge=0, description='确诊数', default=0)
deaths: int = Field(ge=0, description='死亡数', default=0)
recovered: int = Field(ge=0, description='痊愈数', default=0) @app01.put('/request_body/nested')
def nested_models(data: Data):
return data

请求体:

curl -X 'PUT' \
'http://127.0.0.1:8000/app01/request_body/nested' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"city": [
{
"name": "Beijing",
"country": "China",
"country_code": "cn001",
"country_population": 1400000000
}
],
"date": "2023-12-09",
"confirmed": 1000,
"deaths": 10,
"recovered": 9
}'

响应:

{
"city": [
{
"name": "Beijing",
"country": "China",
"country_code": "cn001",
"country_population": 1400000000
}
],
"date": "2023-12-09",
"confirmed": 1000,
"deaths": 10,
"recovered": 9
}

同样用 postman 测试这个 put 请求:

参数验证 - Cookie 和 Header

# 请求头带 Cookie 的效果只能用 Postman 来进行测试哦

@app01.get('/cookie')
def cookie(cookie_id: Optional[str] = Cookie(None)):
return { 'cookie_id': cookie_id } ![](https://img2023.cnblogs.com/blog/1325660/202312/1325660-20231209143316203-281990233.png) @app01.get('/header')
def header(user_agent: Optional[str] = Header(None, convert_underscores=True),
x_token: List[str] = Header(None)
):
# 有些参数不允许下划线的参数哦
return { 'User-Agent': user_agent, 'X-token': x_token }

至此, 关于 FastAPI 请求相关的基础内容学习就可以了, 其测试接口如下:

后面继续学习响应体相关的内容吧!

FastAPI-请求参数与验证的更多相关文章

  1. SpringBoot2.0针对请求参数@RequestBody验证统一拦截

    title: "SpringBoot2.0针对请求参数@RequestBody验证的统一拦截"categories: SpringBoot2.0 Shirotags: Spring ...

  2. Spring注解之Controller中获取请求参数及验证使用

    1.处理request的uri部分的参数:@PathVariable. 2.处理request header部分的参数:@RequestHeader,@CookieValue@RequestHeade ...

  3. 自动化CodeReview - ASP.NET Core请求参数验证

    自动化CodeReview系列目录 自动化CodeReview - ASP.NET Core依赖注入 自动化CodeReview - ASP.NET Core请求参数验证 参数验证实现 在做服务端开发 ...

  4. 使用@Valid和BindingResult验证请求参数的合法性并处理校验结果

    /** * 添加用户,使用@RequestBody将请求体映射到Action方法参数中 * 使用@Valid注解验证请求参数的合法性 * 使用BindingResult处理校验结果 * @param ...

  5. 自研后端HTTP请求参数验证器服务ParamertValidateService

    好处:方便了后端对HTTP请求中参数进行核验,只需一次编写效验器,一行代码便可对所有参数的pojo进行参数核验!而且更改效验逻辑时只需要更改效验器类即可,实现了解耦合. 只需要程序员按照规范开发一个P ...

  6. hibernate-validator验证请求参数

    开发接口要进行请求参数内容格式校验,比如在接收到请求参数后依次需要进行数据内容判空.数据格式规范校验等,十分麻烦,于是尝试用hibernate-validator进行参数校验,简单记录一下使用步骤: ...

  7. Springboot采用hibernate-validate验证请求参数

    在springboot项目使用hibernate-validate对请求参数添加注解进行校验 常用注解 @Null,标注的属性值必须为空 @NotNull,标注的属性值不能为空 @AssertTrue ...

  8. 从零开始设计SOA框架(三):请求参数的加密方式

    第二章中说明请求参数有哪些,主要是公共参数和业务参数,服务端需要对参数进行效验,已验证请求参数的合法性 参数效验前先解释下以下参数: 1.参数键值对:包括公共参数.业务参数      1.公共参数:按 ...

  9. request对象常用API 获取请求参数的值 request应用 MVC设计模式

    1 request对象常用API   1)表示web浏览器向web服务端的请求   2)url表示访问web应用的完整路径:http://localhost:8080/day06/Demo1     ...

  10. Spring请求参数校验

    SpringMVC支持的数据校验是JSR303的标准,通过在bean的属性上打上@NotNull.@Max等进行验证.JSR303提供有很多annotation接口,而SpringMVC对于这些验证是 ...

随机推荐

  1. extern和static

    extern和static extern和static两者之间是有一种相克的关系:用了extern的不能用static,用了static的不能用extern, extern是声明让别的文件中能够使用, ...

  2. 001.GItLab介绍及云原生部署

    目录 gitlab介绍 gitlab cicd简介 gitlab特点 git主要目录 版本区别 gitlab部署 Omnibus 部署 部署需求 安装依赖 导入软件源 正式安装 准备证书 配置SSL及 ...

  3. 一种基于虚拟摄像头、NDI、OBS以及yolo的多机视觉目标检测方案

    一种基于虚拟摄像头.NDI.OBS以及yolo的多机视觉目标检测方案 绪论 近来为了实现某种实时展示效果,笔者希望通过一套方案实现在两台主机上分别运行仿真平台以及视觉深度学习算法.透过对当下较为流行的 ...

  4. 自行为一加6编译Postmarket os内核

    序 在为自己的一加6刷上PostmarketOS后突然某一天想使用它的照相机功能.原因是想到使用pmos拍照后笔者可以直接使用scp指令来传输手机相片到自己运行着GNU/Linux的电脑上,就感到相对 ...

  5. Golang入门:Linux上的go语言安装与配置

    Tips:本文以本文撰写时的 Go 语言最新版本,也就是 go.1.19.2 版本为例. Linux 发行版本使用 Ubuntu 22.04.1 LTS 为例来做演示. 安装 C 工具 Go 的工具链 ...

  6. Linux下对LVM逻辑卷分区大小调整 [针对xfs和ext4文件系统]

    当我们在安装系统的时候,由于没有合理分配分区空间,在后续维护过程中,发现有些分区空间不够使用,而有的分区空间却有很多剩余空间.如果这些分区在装系统的时候使用了lvm(前提是这些分区要是lvm逻辑卷分区 ...

  7. [每日算法 - 华为机试] leetcode680. 验证回文串 II

    入口 力扣https://leetcode.cn/problems/valid-palindrome-ii/submissions/ 题目描述 给你一个字符串 s,最多 可以从中删除一个字符. 请你判 ...

  8. 【安卓】使用Handler出现的警告

    使用Handler出现的警告 零.原由 安卓中使用Hander时出现了如下警告: This Handler class should be static or leaks might occur (a ...

  9. kubectl

    ... Nodes k8s查看节点CPU消耗情况,可以用kubectl top命令,但是会出现 kubectl top nodes error: Metrics API not available 退 ...

  10. chatops

    ChatOps是什么? ChatOps, 简单地说,这是一种方法,允许团队以聊天室的方式来协作和管理其基础结构.代码和数据的许多方面.通过使用聊天机器人和脚本,团队可以执行命令.查询信息,并将知识分发 ...