likeadmin和fastapi的bug

news2024/12/24 21:20:48

以下内容写于2023年8月11日

bug 1

请求体 - 多个参数 - FastAPI (tiangolo.com)中“请求体中的单一值”处,选python3.6,接口示例代码是

from typing import Union

from fastapi import Body, FastAPI
from pydantic import BaseModel
from typing_extensions import Annotated

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Union[str, None] = None
    price: float
    tax: Union[float, None] = None


class User(BaseModel):
    username: str
    full_name: Union[str, None] = None


@app.put("/items/{item_id}")
async def update_item(
    item_id: int, item: Item, user: User, importance: Annotated[int, Body()]
):
    results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
    return results

根据给的请求体的示例代码,我写的请求代码是

import requests

url = 'http://127.0.0.1:8000/items/7'
form_data = {
    "item": {
        "name": "Foo",
        "description": "The pretender",
        "price": 42.0,
        "tax": 3.2
    },
    "user": {
        "username": "dave",
        "full_name": "Dave Grohl"
    },
    "importance": 5
}
response = requests.put(url=url, json=form_data)
print(response.status_code)
print(response.text)

若新建一个python3.8的环境(装好是3.8.17,称为likeadmin环境),然后按照likeadmin的requirements.txt安装库,运行服务端接口代码,再运行请求代码,不能得到正确的结果,提示

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

若新建一个python3.8的环境(装好是3.8.17,称为纯fastapi环境),然后pip install fastapi[all],运行服务端接口代码,再运行请求代码,能得到正确的结果

{"item_id":7,"item":{"name":"Foo","description":"The pretender","price":42.0,"tax":3.2},"user":{"username":"dave","full_name":"Dave Grohl"},"importance":5}

判断结果是否正确的依据是文档中的一句话“在这种情况下,FastAPI 将期望像这样的请求体”。

likeadmin的环境要想得到正确的结果,查看127.0.0.1:8000/docs得知应把importance用问号拼接在请求url中,因为自动生成的文档显示它是query即查询参数。

likeadmin的环境自动生成的文档
纯fastapi环境自动生成的文档

 总结一下就是likeadmin的环境运行fastapi的示例代码,无法得到fastapi文档中说的预期的结果;而新建一个相同python版本的虚拟环境,里面只pip install fastapi[all],可以得到fastapi文档中说的预期的结果。

截止到2023年8月11日,likeadmin的requirements.txt的内容是

aiofiles==22.1.0
aiomysql==0.1.1
alibabacloud_dysmsapi20170525==2.0.23
alibabacloud_tea_openapi
anyio==3.6.1
async-timeout==4.0.2
click==8.1.3
colorama==0.4.5
commonmark==0.9.1
cos-python-sdk-v5==1.9.22
databases==0.6.1
Deprecated==1.2.13
fastapi==0.85.0
fastapi-cache2==0.1.9
fastapi-pagination==0.10.0
greenlet==1.1.3.post0
h11==0.14.0
httptools==0.5.0
idna==3.4
Jinja2==3.1.2
MarkupSafe==2.1.1
optionaldict==0.1.2
oss2==2.16.0
pendulum==2.1.2
psutil==5.9.3
pydantic==1.10.2
Pygments==2.13.0
PyMySQL==1.0.2
python-dateutil==2.8.2
python-dotenv==0.21.0
python-multipart==0.0.5
pytz==2022.5
pytzdata==2020.1
PyYAML==6.0
qiniu==7.9.0
redis==4.4.0rc2
rich==12.6.0
shellingham==1.5.0
six==1.16.0
sniffio==1.3.0
SQLAlchemy==1.4.41
starlette==0.20.4
tencentcloud-sdk-python==3.0.841
typer==0.6.1
typing-extensions==4.4.0
ua-parser==0.16.1
user-agents==2.2.0
# uvloop==0.17.0
uvicorn==0.18.3
watchfiles==0.17.0
websockets==10.3
wrapt==1.14.1
wechatpy==1.8.18

bug 2

与bug1类似,也是likeadmin的环境运行fastapi的示例代码,无法得到fastapi文档中说的预期的结果;而新建一个相同python版本的虚拟环境,里面只pip install fastapi[all],可以得到fastapi文档中说的预期的结果。

请求体 - 多个参数 - FastAPI (tiangolo.com)中“嵌入单个请求体参数”处,选python3.6,接口示例代码是

from typing import Union

from fastapi import Body, FastAPI
from pydantic import BaseModel
from typing_extensions import Annotated

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Union[str, None] = None
    price: float
    tax: Union[float, None] = None


@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
    results = {"item_id": item_id, "item": item}
    return results

文档中说“在这种情况下,FastAPI 将期望像这样的请求体:”

{
    "item": {
        "name": "Foo",
        "description": "The pretender",
        "price": 42.0,
        "tax": 3.2
    }
}

而不是:

{
    "name": "Foo",
    "description": "The pretender",
    "price": 42.0,
    "tax": 3.2
}

根据给的请求体的示例代码,我写的请求代码是

import requests

url = 'http://127.0.0.1:8000/items/7'
form_data_1 = {
    "item": {
        "name": "Foo",
        "description": "The pretender",
        "price": 42.0,
        "tax": 3.2
    }
}
form_data_2 = {
    # "item": {
        "name": "Foo",
        "description": "The pretender",
        "price": 42.0,
        "tax": 3.2
    # }
}
response_1 = requests.put(url=url, json=form_data_1)
response_2 = requests.put(url=url, json=form_data_2)
print(response_1.status_code)
print(response_1.text)
print(response_2.status_code)
print(response_2.text)
# 上面的打印结果:
# fastapi环境
# 200
# {"item_id":7,"item":{"name":"Foo","description":"The pretender","price":42.0,"tax":3.2}}
# 422
# {"detail":[{"type":"missing","loc":["body","item"],"msg":"Field required","input":null,"url":"https://errors.pydantic.dev/2.1/v/missing"}]}
# likeadmin环境
# 422
# {"detail":[{"loc":["body","name"],"msg":"field required","type":"value_error.missing"},{"loc":["body","price"],"msg":"field required","type":"value_error.missing"}]}
# 200
# {"item_id":7,"item":{"name":"Foo","description":"The pretender","price":42.0,"tax":3.2}}

bug 3

Header 参数 - FastAPI (tiangolo.com)中"声明 Header 参数"处(还有Cookie 参数 - FastAPI (tiangolo.com)中"声明 Cookie 参数"处),选python3.6,接口示例代码是

from typing import Union

from fastapi import FastAPI, Header
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/")
async def read_items(user_agent: Annotated[Union[str, None], Header()] = None):
    return {"User-Agent": user_agent}
from typing import Union

from fastapi import Cookie, FastAPI
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/")
async def read_items(ads_id: Annotated[Union[str, None], Cookie()] = None):
    return {"ads_id": ads_id}

 我实际写的接口代码是

from typing import Union

from fastapi import FastAPI, Header, Cookie
from typing_extensions import Annotated

app = FastAPI()

@app.get("/items/")
async def read_items(
    BIDUPSID: Annotated[Union[str, None], Cookie()] = None,  # 从请求头的cookie中获取键为BIDUPSID的值
    PSTM: Annotated[Union[str, None], Cookie()] = None,
    BA_HECTOR: Annotated[Union[str, None], Cookie()] = None,
    user_agent: Annotated[Union[str, None], Header()] = None  # fastapi自动将user_agent转为user-agent,又因HTTP headers是大小写不敏感的,所以user_agent就是User-Agent。from https://fastapi.tiangolo.com/zh/tutorial/header-params/#_1中"自动转换处"
    ):
    return {"Cookie": f'BIDUPSID={BIDUPSID}; PSTM={PSTM}; BA_HECTOR={BA_HECTOR}', "User-Agent": user_agent}

'''
# from https://fastapi.tiangolo.com/zh/tutorial/header-params/#_1中"自动转换处"
自动转换
Header 在 Path, Query 和 Cookie 提供的功能之上有一点额外的功能。

大多数标准的headers用 "连字符" 分隔,也称为 "减号" (-)。

但是像 user-agent 这样的变量在Python中是无效的。

因此, 默认情况下, Header 将把参数名称的字符从下划线 (_) 转换为连字符 (-) 来提取并记录 headers.

同时,HTTP headers 是大小写不敏感的,因此,因此可以使用标准Python样式(也称为 "snake_case")声明它们。

因此,您可以像通常在Python代码中那样使用 user_agent ,而不需要将首字母大写为 User_Agent 或类似的东西。

如果出于某些原因,你需要禁用下划线到连字符的自动转换,设置Header的参数 convert_underscores 为 False
'''

我写的请求代码是

import requests

url = 'http://127.0.0.1:8000/items/'
headers = {
    'Cookie': 'BIDUPSID=A9DA10BEC1294DD8D4F6E654A52CBDC8; PSTM=1691732828; BAIDUID=A9DA10BEC1294DD8402C67E5E8156634:FG=1; BD_UPN=12314753; BA_HECTOR=8h8k05052l000la0a1810h0j1idbjgf1p; BAIDUID_BFESS=A9DA10BEC1294DD8402C67E5E8156634:FG=1; BD_CK_SAM=1; PSINO=2; ZFY=FJzChFI0tlXn0pdMbu9GDJzHS1iNKW8:A:AjdKkCxk2W0:C; delPer=0; BD_HOME=1; COOKIE_SESSION=21_0_0_0_3_0_0_0_0_0_0_0_23_0_4_0_1691734574_0_1691734570%7C2%230_0_1691734570%7C1; H_PS_PSSID=36546_39112_38831_39008_39114_39038_38917_26350_39138_39132_39137_22157_39100; H_PS_645EC=d157JRTS54%2FnnbXzJd5jNKP%2FMviUleulBfUEwB4MIKKEUrwiHAKJcjpnt4A',
    'Referer': 'https://www.baidu.com/',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.203'
}
# cookie = {
#     'BIDUPSID': 'A9DA10BEC1294DD8D4F6E654A52CBDC8',
#     'PSTM': '1691732828',
#     'BA_HECTOR': '8h8k05052l000la0a1810h0j1idbjgf1p'
# }

response = requests.get(url=url, headers=headers)
# response = requests.get(url=url, headers=headers, cookies=cookie)  # 注释掉headers中Cookie,取消cookie的注释,再用这个请求,和上一行的结果一样
print(response.status_code)
print(response.text)

 likeadmin的环境获取不到Cookie和User-Agent;纯fastapi环境,Cookie和User-Agent都能获取。 

# likeadmin的环境的结果
{"Cookie":"BIDUPSID=None; PSTM=None; BA_HECTOR=None","User-Agent":null}

# 纯fastapi环境的结果
{"Cookie":"BIDUPSID=A9DA10BEC1294DD8D4F6E654A52CBDC8; PSTM=1691732828; BA_HECTOR=8h8k05052l000la0a1810h0j1idbjgf1p","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.203"}

bug 4

路径操作配置 - FastAPI (tiangolo.com)中"status_code状态码"处,接口示例代码是

from typing import Set, Union

from fastapi import FastAPI, status
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Union[str, None] = None
    price: float
    tax: Union[float, None] = None
    tags: Set[str] = set()


@app.post("/items/", response_model=Item, status_code=status.HTTP_201_CREATED)  # 也可以直接用status_code=201
async def create_item(item: Item):
    return item

我写的请求代码是

import requests

url = 'http://127.0.0.1:8000/items/'
form_data = {
    'name': 'Bob',
    'price': 12.3,
}
response = requests.post(url=url, json=form_data)
print(response.status_code)
print(response.text)

 likeadmin的环境打印的状态码还是200,没变成设置的201;纯fastapi环境的是201。

bug 1 与 bug 2 与 bug 3 与 bug 4的解决

既然两个虚拟环境的python版本一样,忽然想到是不是fastapi版本不一样导致的,查看纯fastapi环境(2023年8月11日)得到

Package              Version
-------------------- -----------
annotated-types      0.5.0
anyio                3.7.1
certifi              2023.7.22
click                8.1.6
colorama             0.4.6
dnspython            2.4.2
email-validator      2.0.0.post2
exceptiongroup       1.1.2
fastapi              0.101.0
h11                  0.14.0
httpcore             0.17.3
httptools            0.6.0
httpx                0.24.1
idna                 3.4
itsdangerous         2.1.2
Jinja2               3.1.2
MarkupSafe           2.1.3
orjson               3.9.4
pip                  23.2.1
pydantic             2.1.1
pydantic_core        2.4.0
pydantic-extra-types 2.0.0
pydantic-settings    2.0.2
python-dotenv        1.0.0
python-multipart     0.0.6
PyYAML               6.0.1
setuptools           68.0.0
sniffio              1.3.0
starlette            0.27.0
typing_extensions    4.7.1
ujson                5.8.0
uvicorn              0.23.2
watchfiles           0.19.0
websockets           11.0.3
wheel                0.38.4

将likeadmin的fastapi库由0.85.0升级到和纯fastapi环境一样的0.101.0,再运行上面的示例代码,就能得到正确的结果了。

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

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

相关文章

26662-2011 磁粉制动器 阅读笔记

声明 本文是学习GB-T 26662-2011 磁粉制动器. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了磁粉制动器(以下简称制动器)的术语,技术要求,试验方法,检验规则,标志、包装、运 输和…

【项目实战】单数据源多数据库实现多租户

文章目录 前言多租户的四种实现方案单数据源多数据库实现思路代码实现 总结 前言 多租户(Multi-Tenancy)是一种软件架构设计模式,旨在使单个应用程序可以同时为多个租户(如不同组织、用户或客户)提供服务,…

Python 小爬虫入门 -- 爬取专栏文章标题保存到 CSV 文件中

爬取专栏文章标题保存到 CSV 文件中目标分析网页代码及理解代码段一代码段二成果展示爬取专栏文章标题保存到 CSV 文件中 目标 从一个网页上抓取数据,并保存到一个 CSV 文件中。 具体是爬取 微机系统与接口上机实验_TD PITE型 专栏里的所有 文章标题 并 保存到 csv 文件 中…

估计、偏差和方差

一、介绍 统计领域为我们提供了很多工具来实现机器学习目标,不仅可以解决训练集上的任务,还可以泛化。基本的概念,例如参数估计、偏差和方差,对于正式地刻画泛化、欠拟合和过拟合都非常有帮助。 二、参数估计 参数估计 是统计学…

35 LRU缓存

LRU缓存 题解1 双map(差2个testcases)题解2 哈希表双向链表(参考)题解3 STL:listunordered_map 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类: LRUCache(int capacity) 以 正…

通讯网关软件016——利用CommGate X2Access实现OPC数据转储Access

本文介绍利用CommGate X2ACCESS实现从OPC Server读取数据并转储至ACCESS数据库。CommGate X2ACCESS是宁波科安网信开发的网关软件,软件可以登录到网信智汇(http://wangxinzhihui.com)下载。 【案例】如下图所示,实现从OPC Server读取数据并转储至ACCESS…

【前段基础入门之】=>CSS 常用的字体文本属性

导读: 这一章,主要分享一些 CSS 中的一些,常用的 字体和文本方面的属性。 文章目录 字体属性字体大小字体族字体风格字体粗细字体复合写法 文本属性文本间距文本修饰文本缩进文本水平对齐行高vertical-align 字体属性 字体大小 属性名&…

进入Linux的世界

了解Linux的历史 一、Linux发展史二、企业应用现状三、Linux操作系统的各种版本 一、Linux发展史 了解一下硅谷模式: 1945年——1991年是美苏冷战的时间,在这个环境背景下,计算机诞生了。 Linux的发展史: 查看Linux纯源代码 二、企业…

No144.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

完整的 pixel 6a 刷入 AOSP 源码过程记录

基础环境 虚拟机:VMware Workstation 16 Pro 16.0.0 build-16894299 Linux版本:ubuntu-16.04.7-desktop-amd64 设备:pixel 6a;代号:bluejay; 基础软件安装 安装 Git 命令:sudo apt install git …

ATA-M系列功率放大器——应用场景介绍

ATA-M系列是一款理想的单通道功率放大器。最大输出690Vrms电压,800VA功率,可驱动0~100%的阻性或非阻性负载。输出阻抗匹配多个档位可选,客户可根据测试需求调节。 图:ATA-M系列功率放大器 国产品牌安泰电子自主研发的ATA-M系列功率…

MySQL MMM高可用架构

MySQL MMM高可用架构一、MMM概述1、MMM简介2、MMM高可用架构3、MMM故障切换流程 二、MMM高可用双主双从架构部署1、配置主主复制(master),主从复制(slave)1)修改 Master1的MySQL配置文件2)把配置…

Linux 压缩和解压

1、tar命令(复杂) 使用tar命令均可以进行压缩和解压缩的操作 语法:tar [-c -v -x -f -z -C] 参数1 参数2 ... 参数N -c,创建压缩文件,用于压缩模式 -v,显示压缩、解压过程,用于查看进度 -x&am…

redis查看耗时久的命令

redis查看耗时久的命令主要有两招:latency和slow log 【latency】 在Redis中,latency命令用于监视和测量Redis实例的延迟。 先进入redis: redis-cli -h 127.0.0.1 -p 24000[查看延迟监视器阈值] CONFIG GET latency-monitor-threshold这个值返回0&…

N9917A|是德科技keysight N9917A微波分析仪

181/2461/8938毫米波频率测量需要精确和谨慎。幸运的是,随着更多的毫米测试设备问世,工程挑战的难度略有下降。信号分析仪现已将同轴器件的直接覆盖范围扩大到110 GHz。这提供了低噪声、高精度和宽带宽的优势,使工程师能够专注于他们的设计和…

ESP32IDF出现Syntax Warning in cmake code at column 47报错

前言 (1)ESP32的资料还是挺难找的,遇到bug处理起来挺折磨人的。今天分享一个我遇到的bug,以及处理思路。 报错日志 (1)前天在些博客的时候,做测试发现了一个奇怪的bug,报错日志如下。…

Linux 本地 Docker Registry本地镜像仓库远程连接

目录 Linux 本地 Docker Registry本地镜像仓库远程连接 1. 部署Docker Registry 2. 本地测试推送镜像 3. Linux 安装cpolar 4. 配置Docker Registry公网访问地址 5. 公网远程推送Docker Registry 6. 固定Docker Registry公网地址 Linux 本地 Docker Registry本地镜像仓库…

Linux Kernel 之十 虚拟化、VirtIO 架构及规范、VirtQueue VRing

VirtIO 是一种 IO 半虚拟化解决方案,它提供 Guest OS 与 Hypervisor 虚拟化设备之间的通信框架和编程接口。其主要的优势是能提高性能且减少跨平台带来的兼容性问题。本文重点结合 VirtIO 规范 1.1 版以及 Linux 中的源码来分析 VirtIO 框架。 本文是我自己学习虚拟…

【Vue.js】使用Element入门搭建登入注册界面axios中GET请求与POST请求跨域问题

一,ElementUI是什么? Element UI 是一个基于 Vue.js 的桌面端组件库,它提供了一套丰富的 UI 组件,用于构建用户界面。Element UI 的目标是提供简洁、易用、美观的组件,同时保持灵活性和可定制性 二,Element…

idea2023根据表自动生成+springboot跑起来

idea安装插件 idea中显示数据库连接 就可以看到如下界面 选中你想生成的表,右键如下操作 如上就有了所有需要的后端代码 生成后,要查看一下mapper.xml中的文件是否 正确,若有误请先去修改,例如我的版本下生成了xml文件中缺乏…