Python框架篇(2):FastApi-参数接收和验证

 @提示: 如果想获取文章中具体的代码信息,可在微信搜索【猿码记】回复 【fastapi】即可。

1.参数接收

1.1 路径参数(不推荐)

1.代码清单

app/router下,新增demo_router.py文件,内容如下:

from fastapi import APIRouter

router = APIRouter(
    prefix="/demo",
    tags=["演示接口"]
)

@router.get("/path/{order_id}")
async def pathParamReceive(order_id: int):
    """
    路径参数接收演示
    """

    return {
        "接受结果": order_id,
    }

@注意:当我们定义参数类型时,FastAPI 接受参数时,会自动进行"解析",如果类型不一致,则会报错。

2.请求验证
# 正常传参
➜  curl http://127.0.0.1:8000/demo/path/12222
{"接受结果":12222}
# 当传参类型不匹配时,接口定义是:int
➜  curl http://127.0.0.1:8000/demo/path/hello
{"detail":[{"loc":["path","order_id"],"msg":"value is not a valid integer","type":"type_error.integer"}]}
# 当什么都不传时
➜ curl http://127.0.0.1:8000/demo/path/
{"detail":"Not Found"}
3.顺序大坑

假如我们定义两个接口,带路径参数的:/path/{order_id}和不带路径参数的:/path/test,可能会因为顺序问题,导致我们无法正常访问/path/test,例如路由注册时代码如下:

...
@router.get("/path/{order_id}")
async def pathParamReceive(order_id: int):
    """
    路径参数接收-演示-带路径参数
    """

    return {
        "接受结果": order_id,
    }


@router.get("/path/test")
async def pathParamReceive2():
    """
    路径参数接收-演示-不带路径参数
    """

    return {
        "msg""hello",
    }

然后进行访问:

# 带路径参数的可以正常访问
➜  curl http://127.0.0.1:8000/demo/path/99999
{"接受结果":99999}
# 不带路径参数的可以正常访问
➜ curl http://127.0.0.1:8000/demo/path/test
{"detail":[{"loc":["path","order_id"],"msg":"value is not a valid integer","type":"type_error.integer"}]}

通过替换两个函数位置,就可以正常访问了, 感觉比较奇葩,不推荐使用,只做了解即可。更多使用方法可见官方文档: https://fastapi.tiangolo.com/zh/tutorial/path-params/

1.2 查询参数

1.代码清单

app/router下,新增demo_router.py文件,内容如下:

from typing import Union
...
@router.get("/query/receive")
@router.get("/query/receive")
async def queryParamReceive(username: str, sex: str = '男', city: Union[str, None] = None):
    """
    查询参数接受-演示
    """

    return {
        "msg""查询参数接收",
        "result": {
            "username": username,
            "sex": sex,
            "city": city,
        }
    }
...    
2.参数约束
  • username: str: 代表参数 username为必填字段;
  • sex: str = '男': 代表参数 sex为选填字段,并且有默认值 ;
  • city: Union[str, None] = None: 代表参数 city为选填字段, 并无默认值; Uniontyping 模块中的一个泛型类,用于表示多个类型中的一个;

@注意: 当参数有默认值时,顺序一定要放在没有默认值参数后面,否则会提示语法错误:SyntaxError: non-default argument follows default argument

3.请求验证
alt

1.3 请求体(推荐)

使用请求体接受参数,一般分为两个步骤:

  • 第一步: 使用 Pydantic模型声明一个请求体(其实就是 class);
  • 第二步: 路由函数的参数绑定上这个模型;

@注意:工作中比较常用的参数接收方式,推荐使用~

1.定义模型

文件位置: app/parameter/demo_param.py

from typing import Union
# 导入pydantic对应的模型基类
from pydantic import BaseModel

class DemoParam(BaseModel):
    """
    请求体参数对应的模型
    """

    user_name: str
    age: int
    city: Union[str, None]
2.优化导入

文件位置: app/parameter/__init__.py

from app.parameter.demo_param import DemoParam
3.使用

文件位置: app/router/demo_router.py

# from app.parameter.demo_param import DemoParam 如果没有优化导入,需要用这种方式导入
from app.parameter import DemoParam # 如果没有优化导入,这行会报错

router = APIRouter(
    prefix="/demo",
    tags=["演示接口"]
)


@router.post("/query/receive")
async def bodyReceive(body: DemoParam):
    """
    请求体参数接受-演示
    """

    return {
        "msg""请求体参数接受",
        "result": {
            "body": body,
        }
    }
4.验证
# 必填参数user_name,不传时
curl -X 'POST' \
  'http://127.0.0.1:8000/demo/query/body/receive' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "age": 99,
  "city": "北京"
}'


{"detail":[{"loc":["body","user_name"],"msg":"field required","type":"value_error.missing"}]}


# 必填参数user_name,传值时
➜ curl -X 'POST' \
  'http://127.0.0.1:8000/demo/query/body/receive' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "user_name": "娃哈哈",
  "age": 99,
  "city": "北京"
}'

{"msg":"请求体参数接受","result":{"body":{"user_name":"娃哈哈","age":99,"city":"北京"}}}

# 必填参数user_name,传空时
➜  curl -X 'POST' \
  'http://127.0.0.1:8000/demo/query/body/receive' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "user_name": "",
  "age": 99,
  "city": "北京"
}'

{"msg":"请求体参数接受","result":{"body":{"user_name":"","age":99,"city":"北京"}}}

2.参数验证

Python中推荐使用成熟的第三方库进行数据验证,这样不仅可以少写一些if .. elif..,还能让代码的可读性更强;

2.1 Pydantic介绍

Pydantic 是一个 Python 库,用于数据验证和设置,特别是用于验证数据模型。它通过声明性的方式定义数据模型,并提供了强大的数据验证和转换功能。Pydantic 最初是为 FastAPI 框架设计的,但它也可以在其他 Python 项目中独立使用。

@注意: 文中使用的pydantic版本为: 1.10.11, 貌似不同的版本,可能会存在差异;具体可参见官方文档: https://docs.pydantic.dev/latest/

使用Pydantic 的本质,其实就是如何编写对应的数据验证规则,下面列举一些常用的规则:

2.2 常用验证

下面列举一些常用的验证规则:

  • 基本数据类型: int, float, str, bool;
  • 可选参数: Optional[type] 表示可选参数, Union[x, None]也可以表示可选;
  • 整数范围: 结合 conint函数判断数字范围 ,如 age: conint(ge=18, le=30); ge:大于等于、gt:大于、le:小于等于、lt:小于
  • 字符长度: 结合 constr函数判断字符长度,如: constr(min_length=6, max_length=10);
  • 正则表达式: 使用 constr函数中的参数 regex ,可以用于进行正则表达式验证;
  • 枚举验证: 使用 Enum 定义枚举类,验证。
  • 列表类型: 使用 List[type] 来限制列表值的类型,并尝试把参数转成对应的类型。
  • 字典类型: Dict[key_type, value_type] 来限制字典 keyval类型,并尝试把参数转成对应的类型。
from enum import Enum
from typing import Union, Optional, List, Dict

# 导入pydantic对应的模型基类
from pydantic import BaseModel, constr, conint


class GenderEnum(str, Enum):
    """
    性别枚举
    """

    male = "男"
    female = "女"


class PydanticVerifyParam(BaseModel):
    """
    用来学习使用pydantic模型验证
    """

    user_name: str  # 基本类型
    age: conint(ge=18, le=30)  # 整数范围:18 <= age <= 30
    password: constr(min_length=6, max_length=10)  # 字符长度
    phone: constr(regex=r'^1\d{10}$')  # 正则验证手机号
    address: Optional[str] = None  # 可选参数
    sex: GenderEnum  # 枚举验证,只能传: 男和女
    likes: List[str]  # 值会自动转成传字符串列表
    scores: Dict[str, float]  # key会转成字符串,val 会转成浮点型

@注意:上面列举的都是基本使用,实际中可以组合进行多项组合使用,如items: List[constr(min_length=1, max_length=3)] : 限制列表中的每个字符串长度的范围

2.3 自定义验证

@validator 装饰器用于定义自定义验证函数,具体是如下:

from pydantic import BaseModel, constr, conint, validator
...
class PydanticVerifyParam(BaseModel):
    """
    用来学习使用pydantic模型验证
    """

    user_name: str  # 基本类型
    ...
    @validator("user_name")
    def validateUsername(cls, value: str):
        """
        自定义验证函数
        """

        if value.find("傻") > -1:
            raise ValueError("user_name不能包含敏感词")
        return value      

验证结果:

// 当参数user_name传:你好傻
{
  "detail": [
    {
      "loc": [
        "body",
        "user_name"
      ],
      "msg""user_name不能包含敏感词",
      "type""value_error"
    }
  ]
}

2.4 其他验证

  • EmailStr: 用于验证字符串是否是有效的电子邮件地址。
  • IPvAnyAddress: 用于验证字符串是否是有效的 IPv4 或 IPv6 地址。
  • StrictBool: 用于验证字符串是否是严格的布尔值( truefalse)。
  • AnyHttpUrl: 用于验证字符串是否是有效的 URL,包括以 httphttps 开头的 URL

更多验证方式可查看文档: https://docs.pydantic.dev/latest/concepts/validators/

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/144975.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【二分法】

二分法可以在有序排列中&#xff0c;通过不断对半切割数据&#xff0c;提高数据查找效率。 lst [1,4,6,7,45,66,345,767,788,999] n 66 left 0 right len(lst)-1 while left < right: #边界&#xff0c;当右边比左边还小的时候退出循环 mid (left right)//2 …

2023年05月 Python(六级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 明明每天坚持背英语单词,他建立了英语单词错题本文件“mistakes.txt”,将每天记错的单词增加到该文件中,下列打开文件的语句最合适的是?( ) A: f = open(“mistakes.txt”) B: …

2023.11.16 hivesql高阶函数之开窗函数

目录 1.开窗函数的定义 2.数据准备 3.开窗函数之排序 需求:用三种排序方法查询学生的语文成绩排名,并降序显示 4.开窗函数分组 需求:按照科目来分类,使用三种排序方式来排序学生的成绩 5.聚合函数与分组配合使用 6.聚合函数同时和分组以及排序关键字配合使用 --需求1&…

MySQL主主复制

主1 192.168.66.15 主2 192.168.66.16 主1&#xff1a; roottest2 ~]# hostname master1 [roottest2 ~]# bash [rootmaster1 ~]# vim /etc/my.cnf server-id11 log-binmysql-bin auto_increment_increment2 auto_increment_offset1 replicate-do-dbdemo_db …

缩放图片算法优化 sse

前情提要 这里实现了打印文件的缩放算法 缩放打印文件&#xff08;prt,prn&#xff09; 核心功能如下&#xff1a; void CZoomPrtFile::zoomPrtFile(BYTE* pTargetData) {float xRatio static_cast<float>(m_perWidth - 1) / m_zoomWidth;float yRatio static_cast<…

OpenHarmony应用开发入门教程(一、开篇)

前言 华为正式宣布2024年发布的华为鸿蒙OS Next版将不再兼容安卓系统。这一重大改变&#xff0c;预示着华为鸿蒙OS即将进入一个全新的阶段。 都说科技无国界&#xff0c;这是骗人的鬼话。谷歌的安卓12.0系统早已发布&#xff0c;但是自从受到美影响&#xff0c;谷歌就拒绝再向…

网络安全(大厂面试真题集)

前言 随着国家政策的扶持&#xff0c;网络安全行业也越来越为大众所熟知&#xff0c;想要进入到网络安全行业的人也越来越多。 为了拿到心仪的 Offer 之外&#xff0c;除了学好网络安全知识以外&#xff0c;还要应对好企业的面试。 作为一个安全老鸟&#xff0c;工作这么多年…

android studio导入eclipse项目

网上下载一个老工程&#xff0c;.project文件里有eclipse。 android studio导入eclipse项目 eclipse项目结构 Android studio文件结构 下面是导入步骤&#xff1a; 第一步&#xff0c;打开一个项目。 选择File->New->Import Project 第二步&#xff0c;选择Eclipse项目根…

如何设计开发一对一交友App吸引更多活跃用户

在当今社交媒体时代&#xff0c;一对一交友App开发正日渐成为发展热点。如何吸引更多活跃用户成为开发者们的首要任务。通过本文&#xff0c;我们将探讨一系列方法&#xff0c;助您设计开发一对一交友App&#xff0c;吸引更多用户的关注和参与&#xff0c;提升App的活跃度。 了…

elementplus DateTimePicker 日期范围选择器 设置默认时间范围为当前月的起始时间到结束时间

代码如下&#xff1a; <el-date-pickerv-model"value"type"datetimerange"start-placeholder"Start Date"end-placeholder"End Date":default-time"defaultTime" />const defaultTime: [Date, Date] [new Date(2000…

小米手环8pro重新和手机配对解决办法

如果更换了手机&#xff0c;那么小米手环8pro是无法和新手机自动连接的。 但是在新手机上直接连接又连接不上&#xff0c;搜索蓝牙根本找不到手环的蓝牙。 解决办法就是&#xff1a; 把手环恢复出厂&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 是的&…

服务器数据恢复—服务器raid5离线磁盘上线同步失败的数据恢复案例

服务器数据恢复环境&故障&#xff1a; 某品牌DL380服务器中有一组由三块SAS硬盘组建的RAID5阵列。数据库存放在D分区&#xff0c;数据库备份存放在E分区。 服务器上有一块硬盘的状态灯显示红色&#xff0c;D分区无法识别&#xff0c;E分区可识别&#xff0c;但是拷贝文件报…

Node.js详解

一、是什么 Node.js 是一个开源与跨平台的 JavaScript 运行时环境 在浏览器外运行 V8 JavaScript 引擎&#xff08;Google Chrome 的内核&#xff09;&#xff0c;利用事件驱动、非阻塞和异步输入输出模型等技术提高性能 可以理解为 Node.js 就是一个服务器端的、非阻塞式I/…

【XTDrone Ubuntu20.04】XTDrone+ Ubuntu20.04 + PX4安装

XTDrone仿真平台配置 文章目录 XTDrone仿真平台配置依赖安装 ROS一键安装Marvos安装PX4 安装安装QTGroundControlXTDrone下载安装 环境&#xff1a; VMWare 16.0 Ubuntu 22.04 &#xff08;因为没人配过&#xff09;Ubuntu 20.04 参考文章&#xff1a; 仿真平台基础配置 (yuq…

Qt QWebSocket实现JS调用C++

目录 前言1、QWebChannel如何与网页通信2、QWebSocketQWebChannel与网页通信2.1 WebSocketTransport2.2 WebSocketClientWrapper2.3 初始化WebSocket服务器2.4 前端网页代码修改 总结 前言 本篇主要介绍实现JS调用C的另一种方式&#xff0c;即QWebSocketQWebChannel。与之前的…

RabbitMQ之消息应答和持久化

文章目录 前言一、消息应答1.概念2.自动应答3.消息应答方法4.Multiple 的解释5.消息自动重新入队6.消息手动应答代码7.手动应答效果演示 二、RabbitMQ持久化1.概念2.队列如何实现持久化3.消息实现持久化4.不公平分发5.预取值 总结 前言 在RabbitMQ中&#xff0c;我们的消费者在…

SQL题

[极客大挑战 2019]EasySQL 进行简单的尝试&#xff0c;就知道是单引号的字符型注入 万能密码进行一个简单的尝试 结果就出来了 还是要了解一下原理 输入的是1&#xff0c;形成的sql语句是错误的SELECT*FROM table_name WHERE username1and password123; 第一个单引号和第二个…

01Urllib

1.什么是互联网爬虫&#xff1f; 如果我们把互联网比作一张大的蜘蛛网&#xff0c;那一台计算机上的数据便是蜘蛛网上的一个猎物&#xff0c;而爬虫程序就是一只小蜘蛛&#xff0c;沿着蜘蛛网抓取自己想要的数据 解释1&#xff1a;通过一个程序&#xff0c;根据Url(http://www.…

Flutter应用-使用sqflite升级数据库

文章目录 问题描述具体做法代码示例更多条件限制升级 数据库迁移和备份简介数据库迁移数据库备份 问题描述 使用fluttter开发的应用程序发布后&#xff0c;发现数据库有些设计不合理。如何来更新数据库呢&#xff1f; 使用sqflite来处理数据库&#xff0c;但是第一版软件发布后…

JQuery ajax 提交数据提示:Uncaught TypeError:Illegal invocation

JQuery ajax 提交数据提示&#xff1a;Uncaught TypeError:Illegal invocation 1 问题描述 用jQuery Ajax向DRF接口提交数据的时候&#xff0c;console提示&#xff1a;Uncaught TypeError:Illegal invocation(未捕获的异常&#xff1a;非法调用)。 这个问题可能有两种原因导…