美文网首页
FastApi架构学习日记1

FastApi架构学习日记1

作者: livein80 | 来源:发表于2024-01-06 19:27 被阅读0次
FastApi 一个用于构建API的现代的,快速(高性能)的web框架

fastapi 是建立在Starlette 和Pydantic的基础之上的,Starlette 一个轻量级的ASGI框架和工具包,是构建高性能Asyncio服务的理性选择;Pydantic,一个基于python类型提示来定义数据验证,序列化和文档化的库。

一.FastAPI使用的流程:

  1. 导入 FastAPI。
    2.创建一个 app 实例。
    3.编写一个路径操作装饰器(如 @app.get("/"))
    4.编写一个路径操作函数(如上面的 def root(): ...)
    5.运行开发服务器(如 uvicorn main:app --reload)
    a》 main:main.py 文件(一个 Python “模块”)
    b》 app:在 main.py 文件中通过 app = FastAPI() 创建的对象。
    c》 --reload:让服务器在更新代码后重新启动。仅在开发时使用该选项。
# 引入FastAPI类
from fastapi import FastAPI

# 实例化
app = FastAPI()

# 定义路径装饰器和路径操作函数
@app.get("/")
async def root():
    return {"message": "Hello World 老高"}

# 定义路径装饰器和路径操作函数
@app.get("/hello/{name}")
async def say_hello(name: str):
    return {"message": f"Hello {name}"}

2. 在PyCharm中 快捷的使用uvicorn试试服务器

from fastapi import FastAPI
import uvicorn

# 实例化
app = FastAPI()
# 定义路径装饰器和路径操作函数
@app.get("/")
async def root():
    return {"message": "Hello World 老高"}

# 判断该文件是否为主运行文件。
if __name__ == "__main__":
    uvicorn.run("main:app",host='127.0.0.1',port=8080,reload=True)
    #uvicorn.run("文件名称:入口实例名称",host='127.0.0.1',port=8080,reload=True)

二.路径操作

1.路径装饰器

fastapi 支持各种请求方式,如下:

@app.get()
@app.post()
@app.put()
@app.patch()
@app.delete()
@app.option()
@app.head()
@app.trace()

1.主文件路由和子路由,以及APIRouter和include_router的使用
  • 首先定义一个子路由。
    子路由的路径为shopping.apps.app01,文件名称为urls.py
#urls.py 子路由代码如下
# 导入子路由依赖文件 APIRouter
from fastapi import APIRouter

#实例化子路由 路由接口
shop = APIRouter()

#定义子路由的 路由方法
@shop.get('/food/')
async def shop_food():
    return {'shop':'food'}

@shop.get('/bed/')
async def shop_bed():
    return {'shop':'bed'}

  • 定义主入口文件
    include_router 路由分发
# 导入主文件所需依赖
from fastapi import FastAPI
import uvicorn

# 导入子路由
from shopping.apps.app01.urls import shop
from shopping.apps.app02.urls import user


app = FastAPI()

@app.get('/')
async def index():
    return '我是首页'

# 导入子路由(参数分别为 APIRouter,前缀,便签)
app.include_router(shop,prefix='/shop',tags=['购物中心接口'])
app.include_router(user,prefix='/user',tags=['用户中心接口'])


if __name__ == "__main__":
    uvicorn.run("main:app",port=8080,host='127.0.0.1',reload=True)

三.数据请求与响应

1.路径参数和查询参数
  • 路径参数
from fastapi import FastAPI
import uvicorn

# 实例化
app = FastAPI()

# 首页,路径参数
@app.get('/{name}/',tags=['首页接口'])
async def index(name):
    return {'index':'hello ,'+name}
  • 查询参数:除了路径参数以外的参数 都是查询参数。
from fastapi import FastAPI
import uvicorn
from typing import Union,Optional

# 实例化
app = FastAPI()

# 参数可以设置默认值,也可以设置数据类型,数据类型类型可以设置为多个数据类型
# Union 定义数据类型的一个集合,可以设置多个数据类型。Union[str,None] 就等于Optional['str']

@app.get('/login/{name}/',tags=['首页接口'])
async def login(name,psd:Union[str,None]=None,nick:Optional['str']=None):
    return {'index':'hello ,'+name,
            "昵称":nick,
            "密码":psd
            }

2. 请求体

请求体是客户端发送给 API 的数据。响应体是 API 发送给客户端的数据。
我们使用 Pydantic 模型来声明请求体,并能够获得它们所具有的所有能力和优点。

  • 请求体不能够使用GET方法发送,只能使用POST(较常见)、PUT、DELETE 或 PATCH方法之一
  1. pydantic中的模块
  • BaseModel:定义数据模型的基类。它允许你创建具有验证、类型转换和序列化功能的数据模型,以便于数据的输入、处理和输出。
  • Field:定义模型字段(Model Field)的一个函数,Field 函数允许你为 Pydantic 模型的字段指定额外的配置选项,例如数据校验、默认值、别名等。它通常与 Pydantic 的模型类一起使用。
  • validator:添加自定义验证逻辑的装饰器函数。它允许你在 Pydantic 模型中定义验证函数,以便在创建或更新模型实例时执行自定义的数据验证。

2.数据模型的使用

可以限定数据类型,可以使用默认值,可以使用正则表达式,可以多重数据类型嵌套; 还可以使用validator 装饰器,自定义自己的验证规则

# 请求体
from fastapi import APIRouter
from typing import Union,Optional,List

# 请求体 - 导入Pydantic的baseModel
from pydantic import BaseModel,Field,validator
from datetime import date  #引入关于时间的类


app03 = APIRouter()
# 创建数据模型 Addr,声明为参数
class Addr(BaseModel):
    province:str
    city:str

# 创建数据模型 Item
class Item(BaseModel):
    # name:str = Field(regex='^a') # 可以使用正则表达式进行验证
    name:str
    price: int = None
    nick:str
    age:int = Field(default=0,gt=0,lt=100) # 限定区间值,默认值为0,大于0,切小于100的区间值
    description:Union[str,None] = None
    tax:Union[float,None] = None #可以使用多个数据类型集合,可以设置默认值
    dateDay:date = None
    add:Addr     # 多重数据类型嵌套

    # 自定义验证规则,需要引入validator类
    # 自定义name的验证规则,譬如:name 能为字母组合
    @validator("name")
    def name_must_alpha(cls,v):
        assert v.isalpha(),"name must is alpha" # assert 断言,如果v.isalpha()为False时,然后后面提示信息
        return v

    # 自定义nick验证规则,昵称需要字母和数字的组合,并且必须又一个字母为大写字母
    @validator('nick')
    def nick_must_alpha(cls,s):
        # 判断是否同时包含字母和数字
        has_alpha = any(char.isalpha() for char in s)
        has_digit = any(char.isdigit() for char in s)

        # 判断是否包含至少一个大写字母
        has_upper = any(char.isupper() for char in s)

        assert has_alpha and has_digit and has_upper,'nick格式不正确 ,nick 只能是字母+数字+大写的组合'
        return s

@app03.post('/items/')
async def create_item(item:Item):
    return item

3. Form表单

Form 是直接继承自 Body 的类,使用 Form 可以声明与 Body (及 Query、Path、Cookie)相同的元数据和验证。

# 引入Form表单
from fastapi import APIRouter,Form


app04 = APIRouter()

# 使用Form表单的方式接受数据
@app04.post('/regin/')
async def regin_test(username:str=Form(),password:str=Form()):
    print(f'username:{username};password:{password}')
    return {'username':username}

与 JSON 不同,HTML 表单(<form></form>)向服务器发送数据通常使用「特殊」的编码。

  • 表单数据的「媒体类型」编码一般为 application/x-www-form-urlencoded

  • 但包含文件的表单编码为 multipart/form-data

  • 注意事项:

可在一个路径操作中声明多个 Form 参数,但不能同时声明要接收 JSON 的 Body 字段。因为此时请求体的编码是 application/x-www-form-urlencoded,不是 application/json。

这不是 FastAPI 的问题,而是 HTTP 协议的规定。

4. 文件上传

因为上传文件以「表单数据」形式发送,所以接收上传文件,要预先安装 python-multipart

文件上传主要用到2个模块:File和UploadFile。
File一般只适应于小文件上传。大文件或者多文件一般使用UploadFile。

# 引入Form表单
from fastapi import APIRouter,File,UploadFile
from typing import List
import os

app05 = APIRouter()

@app05.post('/file/')
async def get_file(file:bytes = File()):
    # print('get_file-->',file) # 输出为二进制数据
    # 将文件一次性加载到内存,只适合小文件上传,上传大文件到时候会导致内存溢出,性能低下
    return {'file':len(file)}

@app05.post('/files/')
async def get_files(files:List[bytes] = File()):
    # 一次性上传多个文件
    return {'files':len(files)}


@app05.post('/updateFile/')
async def get_updatefile(file:UploadFile):
    # print('UploadFile-->',file)  # 输出:<starlette.datastructures.UploadFile object at 0x1109ab7d0>
    # 文件上传,并保存到服务器
    img = os.path.join('imgs',file.filename)
    with open(img,'wb') as f:
        for line in file.file:
            f.write(line)
    return {'files':file.filename}

@app05.post('/updateFiles/')
async def get_updatefiles(files:List[UploadFile]):
    # 多个文件上传,并保存到服务器
    for file in files:
        img = os.path.join('imgs',file.filename)
        with open(img,'wb') as f:
            for line in file.file:
                f.write(line)
    print('文件写入完成!')

    return {
        'files': [file.filename for file in files]
    }

5. Resquest对象

Fast API 还包含着Resquest模块,Header模块,通过这个模块可以快速的访问用户的头部信息

# Request对象 可以获取一些除了数据之外的其他数据,如文件头信息,IP地址,

from fastapi import APIRouter,Request

app06 = APIRouter()

@app06.post("/get_request/")
async def get_request(res:Request):
    # lst = [i for i in res]
    return {
        '客户端url地址':res.url,
        '客户端ip地址':res.client.host,
        '头信息headers':res.headers,
        'cookie':res.cookies
    }

6. 请求静态文件

静态文件:不是由服务器生成的文件如css,js,图片文件等等。

# 设置网站的静态路径
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles


# 实例化
app = FastAPI()

# 设置静态文件路径,
app.mount('/static',StaticFiles(directory="statics"))

# 通过改地址可以直接访问statics文件夹内的文件。如css文件:http://127.0.0.1:8080/static/css/common.css
7. 响应模型的参数

FastAPI提供response_model参数,来声明return相应体的模型。response_model是「装饰器」的参数,而不是被装饰函数的参数。

FastAPI 将使用此 response_model 来:

  • 将输出数据转换为其声明的类型。
  • 校验数据。
  • 在 OpenAPI 的路径操作中为响应添加一个 JSON Schema。
  • 并在自动生成文档系统中使用。
from fastapi import APIRouter
from pydantic import BaseModel,EmailStr
# 注意如果引入EmailStr后还报错,需要安装一下 
from typing import Union


app07 = APIRouter()

# 接收数据模型
class UserIn(BaseModel):
    username:str
    password:str
    email: EmailStr
    fullname:Union[str,None] = None

# 响应的数据模型
class UserOut(BaseModel):
    username: str
    email: EmailStr
    fullname: Union[str, None] = None

# 注册功能:response_model 给装饰器添加数据模型
@app07.post("/user_reg",response_model=UserOut)
async def user_reg(user:UserIn):
    return user

# 输入值模型需要有username,password,email,fullname 这几个节点。而响应数据只有username,email,fullname 三个节点。这个就是使用响应的数据模型的作用。

响应数据模型其他功能:
  • response_model:返回值响应的数据模型
  • response_model_exclude_unset:过滤掉响应中的默认值,而是仅有实际设置的值
  • response_model_exclude_none=True: 相应值中不返回none的值
  • response_model_exclude_defaults=True:相应值中返回默认值
  • response_model_include: 相应值中只返回include包含的数据
  • response_model_exclude:相应值中不返回include包含的数据

使用路径操作装饰器的 response_model 参数来定义响应模型,特别是确保私有数据被过滤掉。

response 其他功能demo :
#+++++++++++++++++++++++++++++++++++
class Item(BaseModel):
    name: str
    description: Union[str, None] = None
    price: float
    tax: float = 10.5
items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2},
    "baz": {
        "name": "Baz",
        "description": "There goes my baz",
        "price": 50.2,
        "tax": 10.5,
    },
}

@app07.get(
    "/reponse/{item_id}/name",
    response_model=Item,
    response_model_include={"name", "description"},
)
async def read_item_name(item_id: str):
    return items[item_id]

相关文章

网友评论

      本文标题:FastApi架构学习日记1

      本文链接:https://www.haomeiwen.com/subject/vjepndtx.html