FastAPI从入门到实战(10)——响应模型与状态码

2023-11-03

前面一直记录的是请求相关的内容,这篇文章开始记录一下响应相关的内容,包括请求模型和模型继承以及状态码等相关的内容。

一个任意dict构成的基本响应

# 任意dict构成的响应
@app06.get("/stu06/dict", response_model=Dict[str, float])
async def stu06_read_keyword_weights():
    return {"foo": 2.3, "bar": 3.4}

上面是用Dict声明的一个响应模型,只需要声明键和值的类型,就能直接响应。

image-20221129181122307

定义基本响应模型

# 定义一个基本模型类
class userIn(BaseModel):
    username: str
    password: str
    email: EmailStr
    sex: str
    age: int


# 响应模型:输出与输入相同的模型数据
@app06.post("/stu06/user_response", response_model=userIn)
def stu06_creat_user(user: userIn):
    return user

这里利用Pydantic定义一个基本的模型类,包含username、password等字段,然后声明一个post请求,请求参数默认Query类型,服务器接受到请求后将接收的数据再次以userIn的类型进行返回。

image-20221129224540214

定义输出响应模型

# 添加一个输出模型类
class userOut(BaseModel):
    username: str
    email: EmailStr
    sex: Optional[str] = "girl"
    age: Optional[int] = None


# 响应输出模型
@app06.post("/stu06/userout", response_model=userOut)
def stu06_response_userout(user: userIn):
    return user

上面的例子不太能反映响应模型类的作用,为了更清楚的展示,这里重新定义一个类,类的名称叫做userOut,相较于上面的例子,少了一个password参数,然后同样是一个post请求,服务器接受一个userIn类型的参数,然后将接收的数据以userOut类型进行返回,响应结果就没有了password字段。

image-20221129224655033

为模型设置值

userItem = {
    "name1": {"username": "name1", "password": "12312312", "email": "hidbiuwu@nenu.edu.cn"},
    "name2": {"username": "name2", "password": "12312312", "email": "hidddwu@163.com", "sex": "girl", "age": 25},
    "MinChess": {"username": "MinChess", "password": "12312312", "email": "MinChess@jiumoz.com", "sex": None,
                 "age": 22}
}


# 响应详细参数
@app06.get("/stu06/response_item", response_model=userOut)
def stu06_response_item(
        username: str = Query(...)
):
    return userItem[username]

通常web开发中,响应的数据都是从数据库进行请求的,比如说用户登录,请求的时候只会发送用户名和密码,返回就需要返回之前用户注册的时候填的更多的基本信息,例如姓名、性别、年龄等;

这里我们首先定义一个字典userItem,字典的keyusername的值,value为一个字典;然后定义一个get请求,请求参数为username;前端发送一个带有username的请求,服务器接收请求后,在userItem中进行匹配,匹配到对应的字段后以userOut类型的形式进行返回。

image-20221129224833928

响应字段控制

忽略未设置的参数 response_model_exclude_nset

# 响应未经参数设置的参数 response_model_exclude_nset=True
@app06.get("/stu06/response_exclude_unset", response_model=userOut, response_model_exclude_unset=True)
def stu06_response_item_exclude_unset(
        username: str = Query("name1")
):
    return userItem[username]

如上一个例子,当usernamename1的时候,返回是字段是userOut内所有的字段,但是名为name1的字典内,并没有age、sex的字段;遇到这种情况,就可以通过设置参数response_model_exclude_nset=True来进行控制;

image-20221129224849330

响应忽略默认值response_model_exclude_defaults

# 响应忽略和默认值一样的字段 response_model_exclude_defaults=True
@app06.get("/stu06/response_exclude_defaults", response_model=userOut, response_model_exclude_defaults=True)
def stu06_response_item_exclude_defaults(
        username: str = Query("name2")
):
    return userItem[username]

同样,我们拿到数据发现和默认数据是相同的时候,需要自动忽略,就可以通过设置参数response_model_exclude_defaults=True来实现,即我们发现uesrItem内,名为name2的字典内sex字段和定义的userOut响应模型类的默认值是一样的,我们就进行忽略;

当然实际情况肯定不会是默认一个性别吭…

image-20221129224905361

响应忽略None字段response_model_exclude_none

# 响应忽略None字段 response_model_exclude_none=True
@app06.get("/stu06/response_exclude_none", response_model=userOut, response_model_exclude_none=True)
def stu06_response_item_exclude_none(
        username: str = Query("MinChess")
):
    return userItem[username]

同理,我们需要忽略空字段的时候,就可以通过设置response_model_exclude_none=True参数来实现了,实际应用就是数据库中,某些字段为空会影响用户的体验,那么就可以直接这样设置来过滤空字段;

上面的例子就是,名为MinChess的字段内,sex字段为None,那么我们就不进行返回。

image-20221129224930523

响应只包含指定字段 response_model_include

# 响应只包含指定字段 response_model_include
@app06.get("/stu06/response_model_include", response_model=userOut, response_model_include=["username","age"])
def stu06_response_model_include(
        username:str = Query("MinChess")
):
    return userItem[username]

我们定义的模型类可能不适用于所有场景,有些页面只需要头像或者姓名,但是重新定义一个类在参数很多的情况下就完全没必要,所以就可以手动进行指定,如上面的例子response_model_include=["username","age"],指定返回usernameage字段。

image-20221129224945565

响应排除指定字段 response_model_exclude

# 响应排除指定字段 response_model_exclude
@app06.get("/stu06/response_model_exclude", response_model=userOut,response_model_exclude=["email"])
def stu06_response_model_exclude(
        username:str = Query("MinChess")
):
    return userItem[username]

弄清楚了上面那个,这个就很容易了,就是忽略某些字段嘛,这里就是忽略email字段。

image-20221129225006030

模型列表

# 模型列表
@app06.get("/stu06/response_users",response_model=List[userOut], response_model_exclude_none=True)
def sru06_response_users(
        username1: Optional[str] = Query("name1"),
        username2: Optional[str] = Query("name2")
):
    return [userItem[username1],userItem[username2]]

模型列表就是响应的内容是一个列表,列表是我们定义的某个模型类类别的,比如管理系统,返回的就是很多个相同类的数据,但是实际应用肯定不是像这里这样传这么多username哈!

这里就直接设置response_modelList类型的就行,其中List为userOut类的;

image-20221129225036700

模型继承

# 基本类
class loginbase(BaseModel):
    phone_number:str
    name:str
# 登录时用到的类,在此基础上,需要增加密码和验证码的字段
class login(loginbase):
    password:str
    code:str
# 登录成功后返回给前端的类,返回的字段和基本类相同,不需要增加或删除,直接pass
class loginsuccess(loginbase):
    pass
# 存储至数据库时的类,在基本模型基础上要添加一个经过处理的密码
class logindb(loginbase):
    hash_password:str
# 伪密码处理函数
def password_hash(password:str):
    return "hash——"+password
# 伪入库类:接收前端传来的login类
def login_database(loginparam:login):
    # 将接收到的login类型下loginparam中的password字段进行处理(加密)
    hashpassword = password_hash(loginparam.password)
    # 首先通过Pydantic模型的.dict()方法将loginparam处理为拥有模型数据的dict
    # 再通过**将其中的参数传递到logindb中,python对其进行解包,便能一一对应进行直接传递了
    # 同时对hash_password进行另外关键字参数的设置
    login_db = logindb(**loginparam.dict(),hash_password=hashpassword)
    print("入库成功!",login_db.dict())
    # 返回logindb类型的数据
    return login_db

@app06.post("/stu06/login",response_model=loginsuccess)
async def stu06_login(login_param:login):
    # 返回请求成功的类型的数据
    loginsuc = login_database(login_param)
    return loginsuc

这个部分其实不主要记录关于响应相关的内容,主要是记录一种思想,实际应用中就是对于同一个user表,登录、响应、存储所涉及的字段都是不同的,所以可以通过定义基本的类,然后进行继承来实现扩展。这样可以减少大量的重复代码;

具体的一些知识点和操作参看上面的注释,写的很明白!

image-20221129225408766

状态码设置

HTTP状态码

HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字有分类的作用。不同的状态码代表不同的含义。

HTTP状态码分类

共分为5种类型:

分类 分类描述
1xx 信息,服务器收到请求,需要请求者继续执行操作
2xx 成功,操作被成功接收并处理
3xx 重定向,需要进一步的操作以完成请求
4xx 客户端错误,请求包含语法错误或无法完成请求
5xx 服务器错误,服务器在处理请求的过程中发生了错误

常见状态码&含义

200 - 请求成功,已经正常处理完毕

301 - 请求永久重定向,转移到其它URL

302 - 请求临时重定向

304 - 请求被重定向到客户端本地缓存

400 - 客户端请求存在语法错误

401 - 客户端请求没有经过授权

403 - 客户端的请求被服务器拒绝,一般为客户端没有访问权限

404 - 客户端请求的URL在服务端不存在

500 - 服务端永久错误

直接利用数字声明

@app06.get("/stu06/statuscode",status_code=200)
async def stu06_status():
    return {"status-code":200}

上面的代码,就是直接在请求声明中定义了响应状态码为200;

image-20221129180157668

利用FastAPI进行设置

@app06.get("/stu06/statuscode_fastapi",status_code=status.HTTP_200_OK)
def stu06_fastcode():
    return {"status-code":200}

这里就是利用fastapi.status进行设置的便捷变量

image-20221129180401422

源码

# -*- coding: utf-8 -*-
# @Time: 2022/11/29 11:17
# @Author: MinChess
# @File: stu06.py
# @Software: PyCharm

from fastapi import APIRouter, Query ,status
from pydantic import BaseModel, EmailStr, Field
from typing import Optional,List,Dict

app06 = APIRouter()

# 任意dict构成的响应
@app06.get("/stu06/dict", response_model=Dict[str, float])
async def stu06_read_keyword_weights():
    return {"foo": 2.3, "bar": 3.4}


# 定义一个基本模型类
class userIn(BaseModel):
    username: str
    password: str
    email: EmailStr
    sex: str
    age: int


# 响应模型:输出与输入相同的模型数据
@app06.post("/stu06/user_response", response_model=userIn)
def stu06_creat_user(user: userIn):
    return user


# 添加一个输出模型类
class userOut(BaseModel):
    username: str
    email: EmailStr
    sex: Optional[str] = "girl"
    age: Optional[int] = None


# 响应输出模型
@app06.post("/stu06/userout", response_model=userOut)
def stu06_response_userout(user: userIn):
    return user

userItem = {
    "name1": {"username": "name1", "password": "12312312", "email": "hidbiuwu@nenu.edu.cn"},
    "name2": {"username": "name2", "password": "12312312", "email": "hidddwu@163.com", "sex": "girl", "age": 25},
    "MinChess": {"username": "MinChess", "password": "12312312", "email": "MinChess@jiumoz.com", "sex": None,
                 "age": 22}
}


# 响应详细参数
@app06.get("/stu06/response_item", response_model=userOut)
def stu06_response_item(
        username: str = Query(...)
):
    return userItem[username]


# 响应未经参数设置的参数 response_model_exclude_nset=True
@app06.get("/stu06/response_exclude_unset", response_model=userOut, response_model_exclude_unset=True)
def stu06_response_item_exclude_unset(
        username: str = Query("name1")
):
    return userItem[username]

# 响应忽略和默认值一样的字段 response_model_exclude_defaults=True
@app06.get("/stu06/response_exclude_defaults", response_model=userOut, response_model_exclude_defaults=True)
def stu06_response_item_exclude_defaults(
        username: str = Query("name2")
):
    return userItem[username]

# 响应忽略None字段 response_model_exclude_none=True
@app06.get("/stu06/response_exclude_none", response_model=userOut, response_model_exclude_none=True)
def stu06_response_item_exclude_none(
        username: str = Query("MinChess")
):
    return userItem[username]

# 响应只包含指定字段 response_model_include
@app06.get("/stu06/response_model_include", response_model=userOut, response_model_include=["username","age"])
def stu06_response_model_include(
        username:str = Query("MinChess")
):
    return userItem[username]

# 响应排除指定字段 response_model_exclude
@app06.get("/stu06/response_model_exclude", response_model=userOut,response_model_exclude=["email"])
def stu06_response_model_exclude(
        username:str = Query("MinChess")
):
    return userItem[username]

# 模型列表
@app06.get("/stu06/response_users",response_model=List[userOut], response_model_exclude_none=True)
def sru06_response_users(
        username1: Optional[str] = Query("name1"),
        username2: Optional[str] = Query("name2")
):
    return [userItem[username1],userItem[username2]]


# 基本类
class loginbase(BaseModel):
    phone_number:str
    name:str
# 登录时用到的类,在此基础上,需要增加密码和验证码的字段
class login(loginbase):
    password:str
    code:str
# 登录成功后返回给前端的类,返回的字段和基本类相同,不需要增加或删除,直接pass
class loginsuccess(loginbase):
    pass
# 存储至数据库时的类,在基本模型基础上要添加一个经过处理的密码
class logindb(loginbase):
    hash_password:str
# 伪密码处理函数
def password_hash(password:str):
    return "hash——"+password
# 伪入库类:接收前端传来的login类
def login_database(loginparam:login):
    # 将接收到的login类型下loginparam中的password字段进行处理(加密)
    hashpassword = password_hash(loginparam.password)
    # 首先通过Pydantic模型的.dict()方法将loginparam处理为拥有模型数据的dict
    # 再通过**将其中的参数传递到logindb中,python对其进行解包,便能一一对应进行直接传递了
    # 同时对hash_password进行另外关键字参数的设置
    login_db = logindb(**loginparam.dict(),hash_password=hashpassword)
    print("入库成功!",login_db.dict())
    # 返回logindb类型的数据
    return login_db

@app06.post("/stu06/login",response_model=loginsuccess)
async def stu06_login(login_param:login):
    # 返回请求成功的类型的数据
    loginsuc = login_database(login_param)
    return loginsuc

# 直接修改
@app06.get("/stu06/statuscode",status_code=200)
async def stu06_status():
    return {"status-code":200}

# 通过fastapi设置
@app06.get("/stu06/statuscode_fastapi",status_code=status.HTTP_200_OK)
def stu06_fastcode():
    return {"status-code":200}

感谢阅读!

博客链接:FastAPI从入门到实战(10)——响应模型与状态码

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FastAPI从入门到实战(10)——响应模型与状态码 的相关文章

随机推荐

  • shell脚本实战-while循环语句

    前言 上文我们讨论了for循环的使用 在有限循环里 我们使用for循环是很方便的一件事情 今天我们来探讨下while循环 while循环语句的语法分析 语法格式一 while 条件 do 操作 done 语法格式二 while read l
  • 生成随机小数的函数python_哪个选项是random库中用于生成随机小数的函数?

    其它 一个整数 它加上100后是一个完全平方数 再加上168又是一个完全平方数 试编写代码输出该整数 要求 1 粘贴代码图片 图片需包括行号 代码不可超过6行 争取4行 2 粘贴结果图片 符合条件的整数有四个 单选题 哪个选项不能正确引用t
  • PD16 for Mac(支持M1芯片)v16.3.2(50531)中文版介绍

    PD16虚拟机中文版是mac上最强大也是最好用的虚拟机软件 Parallels Desktop Mac 16 可以显着降低磁盘 内存和CPU使用率 而且针对Windows 10更新进行了优化 更新了超过50个新功能 可以让您更充分地利用你的
  • Out-Of-Vocabulary(OOV)的理解

    OOV 问题是NLP中常见的一个问题 其全称是Out Of Vocabulary 下面简要的说了一下OOV 怎么解决 下面说一下Bert中是怎么解决OOV问题 如果一个单词不在词表中 则按照subword的方式逐个拆分token 如果连逐个
  • 汉字简/繁体转换

  • C语言:删除字符

    本题要求实现一个删除字符串中的指定字符的简单函数 函数接口定义 void delchar char str char c 其中char str是传入的字符串 c是待删除的字符 函数delchar的功能是将字符串str中出现的所有c字符删除
  • 【kernel envirment】config tiny X86 kernel with vfs

    Automatically generated file DO NOT EDIT Linux x86 4 19 0 Kernel Configuration Compiler gcc Ubuntu 7 3 0 27ubuntu1 18 04
  • cocos creator 血条跟随3d convertToUINode导致的问题,使用worldToScreen解决跟随偏离问题

    cocos creator3 3 2 实现血条跟随 一开始使用的camera的converToUINode 也是按照麒麟子大师的博客操作 结果最终的效果 在屏幕中间 血条显示正常 在屏幕边缘就开始出现偏差 x和y都有的偏差 最终也没有解决方
  • 择后自动上传html代码,GitLab + Jenkins + Webhook 实现Push代码后自动更新

    一 介绍 通常是开发后的代码先推到Gitlab上管理 然后在Jenkins里通过脚本构建代码发布 这种方式每次在发版的时候 需要人工去执行jenkins上的构建动作 有时显得过于繁琐 Gitlab的Webhook功能 通过Webhook的相
  • 九月份参加OPPO和腾讯Android面试:技术一面+二面+三面+HR四面,我的面经总结!

    之前很多时候我是拒绝说我的面试经验的 因为我们简历经历不一样问的问题也会不一样 且大厂面试光靠背几个面试题就想过还是比较难的 因此在这里提醒一下大家不要临时抱佛脚 你花几天能背下的东西 别人花几天一定能超过你的 但我们花几年沉淀的东西 人家
  • 公司企业微信小程序创建步骤

    随着新一代互联网的发展 小程序已经成为当今社会不可或缺的重要部分 它的简单易用 公司企业小程序是一种基于微信平台构建的应用程序 旨在为企业提供灵活便捷的营销服务 关于公司企业微信小程序创建步骤 可分为以下几个部分 一 申请微信公众号并创建小
  • 2022年,软件测试还能学吗?别学了,软件测试岗位饱和了...

    8年前 我懵懂的选择了软件测试这个行业 穷困潦倒的时候 爸妈给我付了2万块钱进入了一家培训机构 我怀着感激和破釜沉舟的情绪开始学习软件测试 3个月的学习时间 住群租宿舍 吃盒饭 平时上课认真听讲 周末就跑自习室 在学了基础课程之后 找工作的
  • vue中纯JS调用自定义组件

    案例以vant为例 1 首先创建index vue index js文件 2 index vue跟我们平常写的组件是一样的
  • 51单片机学习笔记(十二) - 红外遥控

    文章目录 前言 一 红外遥控的背景知识 1 人机交互 2 红外遥控的相关知识 二 原理图电路分析 三 NEC协议讲解 1 逻辑1与逻辑0的表示 2 NEC协议格式 3 NEC协议的关键点 四 代码实现 总结 前言 随着科技的发展 红外遥控器
  • 【Spring Boot整合MyBatis教程】

    Spring Boot是由Pivotal团队提供的全新框架 其设计目的是用来简化新Spring应用的初始搭建以及开发过程 该框架使用了特定的方式来进行配置 从而使开发人员不再需要定义样板化的配置 通过这种方式 Spring Boot致力于在
  • 用4种语言编写端口扫描器(Java、C、Python、Go)

    Java import java net InetSocketAddress import java net Socket import java util concurrent ExecutorService import java ut
  • Ghost-Docker(五)Nginx+SSL+Https

    使用 Ngins SSL 证书 为 Ghost 实现 Https 访问 HTTPS 协议是由 HTTP 加上 TLS SSL 协议构建的可进行加密传输 身份认证的网络协议 主要通过数字证书 加密算法 非对称密钥等技术完成互联网数据传输加密
  • ElementUI过渡动画篇

    ElementUI过渡动画篇 element官方提供的过渡动画并不能很好的满足使用 我尝试过几种过渡动画的设置方式 最终选择了Animate css 一 使用方法 引入 引入 npm install animate css save 然后在
  • 保姆级连载讲义学Python:第四篇多文件项目的演练

    多文件项目的演练 开发 项目 就是开发一个 专门解决一个复杂业务功能的软件 通常每 一个项目 就具有一个 独立专属的目录 用于保存 所有和项目相关的文件 一个项目通常会包含 很多源文件 目标 在项目中添加多个文件 并且设置文件的执行 多文件
  • FastAPI从入门到实战(10)——响应模型与状态码

    前面一直记录的是请求相关的内容 这篇文章开始记录一下响应相关的内容 包括请求模型和模型继承以及状态码等相关的内容 一个任意dict构成的基本响应 任意dict构成的响应 app06 get stu06 dict response model