【python】fastAPI学习笔记(3)

请求体

from typing import Optional
import uvicorn
from fastapi import Body, FastAPI, Path
from pydantic import BaseModel

app = FastAPI()

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

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

# 混合Path、Query 请求体参数
# 多个请求体参数 item user
# importance 默认情况 单一值被解释为查询参数, body同样有数据校验机制
# embed 将原本的请求体嵌入到一个键中
@app.put("/items/{item_id}")
async def update_item(
    *,
    item_id: int = Path(..., title="The ID of the item to get", ge=0, le=1000),
    q: Optional[str] = None,
    item: Optional[Item]=Body(..., embed=True),
    # item: Optional[Item] = None,
    user: User,
    importance: int = Body(..., gt=0)
):
    results = {"item_id": item_id, 'user': user, 'importance': importance}
    if q:
        results.update({"q": q})
    if item:
        results.update({"item": item})
    return results

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000, loop="asyncio")

请求体-字段 feild

from typing import Optional
import uvicorn
from fastapi import Body, FastAPI
from pydantic import BaseModel, Field

app = FastAPI()

class Item(BaseModel):
    name: str
    description: Optional[str] = Field(
        None, title="The description of the item", max_length=300
    )
    price: float = Field(..., gt=0, description="The price must be greater than zero")
    tax: Optional[float] = None

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

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000, loop="asyncio")

请求体-嵌套模型

from typing import List, Optional, Set, Dict
import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl

app = FastAPI()

class Image(BaseModel):
    # url: str
    name: str
    url: HttpUrl

# list -> List -> Set
# 嵌套数据模型
# str -> HttpUrl
# 一组子模型 List[Image]
class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None
    # tags: list = []  #
    # tags: List[int] = []
    tags: Set[str] = set()
    image: Optional[Image] = None
    images: Optional[List[Image]] = None

# 多层嵌套
class Offer(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    items: List[Item]

@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
    results = {"item_id": item_id, "item": item}
    return results

@app.post('/offers/')
async def create_offer(offer: Offer):
    return offer

# 返回列表[] 而非{}
@app.post('/images/multiple')
async def create_multiple_images(images: List[Image]):
    return images

@app.post("/index-weights/")
async def create_index_weights(weights: Dict[int, float]):
    print(weights)
    return weights

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000, loop="asyncio")

 

添加额外的信息

from typing import Optional
import uvicorn
from fastapi import FastAPI, Body
from pydantic import BaseModel, Field

app = FastAPI()
# 添加额外信息
# 法1:使用Config和schema_extra
# 法2:Field、body等 example

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

    class Config:
        schema_extra = {
            "example": {
                "name": "Foo",
                "description": "A very nice Item",
                "price": 35.4,
                "tax": 3.2,
            }
        }

class Item1(BaseModel):
    name: str = Field(..., example="Foo")
    description: Optional[str] = Field(None, example="A very nice Item")
    price: float = Field(..., example=35.4)
    tax: Optional[float] = Field(None, example=3.2)

@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, item1: Item1, item2: Item = Body(
    ...,
    example={
        "name": "Foo",
        "description": "A very nice Item",
        "price": 35.4,
        "tax": 3.2,
    }
)):
    results = {"item_id": item_id, "item": item, "item1": item1, 'item2': item2}
    return results

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000, loop="asyncio")

 

其余数据类型

# 基础数据类型 int float str bool
# UUID、datetime.datetime datetime.date datetime.time datetime.timedelta、 frozenset、 bytes、 Decimal

from datetime import datetime, time, timedelta
from typing import Optional
from uuid import UUID
from fastapi import Body, FastAPI
import uvicorn
app = FastAPI()

# https://1024tools.com/uuid
@app.put("/items/{item_id}")
async def read_items(
    item_id: UUID,
    start_datetime: Optional[datetime] = Body(None),
    end_datetime: Optional[datetime] = Body(None),
    repeat_at: Optional[time] = Body(None),
    process_after: Optional[timedelta] = Body(None),
):
    start_process = start_datetime + process_after
    duration = end_datetime - start_process
    return {
        "item_id": item_id,
        "start_datetime": start_datetime,
        "end_datetime": end_datetime,
        "repeat_at": repeat_at,
        "process_after": process_after,
        "start_process": start_process,
        "duration": duration,
    }

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000, loop="asyncio")

 

cookie header

要想获取cookie、header 浏览器中需要有相应的属性值

from typing import Optional,List
from fastapi import Cookie, FastAPI, Header
import uvicorn

app = FastAPI()

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

@app.get("/items1/")
async def read_items(user_agent: Optional[str] = Header(None)):
    return {"User-Agent": user_agent}

@app.get("/items2/")
async def read_items(
    strange_header: Optional[str] = Header(None, convert_underscores=False)
):
    return {"strange_header": strange_header}

@app.get("/items3/")
async def read_items(x_token: Optional[List[str]] = Header(None)):
    return {"X-Token values": x_token}
if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000, loop="asyncio")

响应模型

response_model参数

mac 无法安装pydantic[email],执行pip install email-validator 和 pip install typing_extensions即可

response_model_exclude_unset等参数,对返回结果进行限制

from typing import List, Optional
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
import uvicorn
app = FastAPI()


class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None
    tags: List[str] = []

class UserIn(BaseModel):
    username: str
    password: str
    email: EmailStr
    full_name: Optional[str] = None

class UserOut(BaseModel):
    username: str
    email: EmailStr
    full_name: Optional[str] = None

# Don't do this in production!
# @app.post("/user/", response_model=UserIn)
# async def create_user(user: UserIn):
#     return user

@app.post("/user/", response_model=UserOut)
async def create_user(user: UserIn):
    return user

@app.post("/items/", response_model=Item)
async def create_item(item: Item):
    return item

items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
    "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}
@app.get("/items/{item_id}",
         response_model=Item,
         response_model_exclude_unset=True) # 忽略默认值
async def read_item(item_id: str):
    return items[item_id]

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

@app.get("/items/{item_id}/public",
         response_model=Item,
         response_model_exclude={"tax"})
async def read_item_public_data(item_id: str):
    return items[item_id]
if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000, loop="asyncio")

 

额外的模型

尽量减少代码的重复,封装公共模块

from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
import uvicorn

app = FastAPI()


class UserBase(BaseModel):
    username: str
    email: EmailStr
    full_name: Optional[str] = None


# class UserIn(BaseModel):
#     username: str
#
#     password: str
#
#     email: EmailStr
#     full_name: Optional[str] = None

class UserIn(UserBase):
    password: str


# class UserOut(BaseModel):
#     username: str
#     email: EmailStr
#     full_name: Optional[str] = None

class UserOut(UserBase):
    pass


# class UserInDB(BaseModel):
#     username: str
#
#     hashed_password: str
#
#     email: EmailStr
#     full_name: Optional[str] = None

class UserInDB(UserBase):
    hashed_password: str


def fake_password_hasher(raw_password: str):
    return "supersecret" + raw_password


def fake_save_user(user_in: UserIn):
    hashed_password = fake_password_hasher(user_in.password)

    user_in_db = UserInDB(**user_in.dict(), hashed_password=hashed_password)

    print("User saved! ..not really")
    return user_in_db


@app.post("/user/", response_model=UserOut)
async def create_user(user_in: UserIn):
    user_saved = fake_save_user(user_in)
    return user_saved


if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000, loop="asyncio")

多个数据模型进行切换

from typing import Union, List, Dict

from fastapi import FastAPI
from pydantic import BaseModel
import uvicorn
app = FastAPI()


class BaseItem(BaseModel):
    description: str
    type: str


class CarItem(BaseItem):
    type = "car"


class PlaneItem(BaseItem):
    type = "plane"

    size: int


items = {
    "item1": {"description": "All my friends drive a low rider", "type": "car"},
    "item2": {
        "description": "Music is my aeroplane, it's my aeroplane",
        "type": "plane",
        "size": 5,
    },
}

class Item(BaseModel):
    name: str
    description: str


items = [
    {"name": "Foo", "description": "There comes my hero"},
    {"name": "Red", "description": "It's my aeroplane"},
]

@app.get("/items/{item_id}", response_model=Union[PlaneItem, CarItem]) # union
async def read_item(item_id: str):
    return items[item_id]

@app.get("/items/", response_model=List[Item]) # 模型列表
async def read_items():
    return items

@app.get("/keyword-weights/", response_model=Dict[str, float])
async def read_keyword_weights():
    return {"foo": 2.3, "bar": 3.4}
if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000, loop="asyncio")

 

响应码

from fastapi import FastAPI, status
import uvicorn

app = FastAPI()

# 200 成功、 300 重定向 400 客户端错误
# @app.post("/items/", status_code=201)
@app.post("/items/", status_code=status.HTTP_201_CREATED)
async def create_item(name: str):
    return {"name": name}


if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000, loop="asyncio")

form

from fastapi import FastAPI, Form
import uvicorn

app = FastAPI()


@app.post("/login/")
async def login(username: str = Form(...), password: str = Form(...)):
    return {"username": username}


if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000, loop="asyncio")

 

文件

from typing import List
from fastapi import FastAPI, File, UploadFile
from fastapi.responses import HTMLResponse
import uvicorn

app = FastAPI()


@app.post("/files/")
async def create_file(file: bytes = File(...)):
    return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
    contents = await file.read()
    return {"filename": file.filename, 'contents': contents}

@app.post("/files1/")
async def create_files(files: List[bytes] = File(...)):
    return {"file_sizes": [len(file) for file in files]}


@app.post("/uploadfiles1/")
async def create_upload_files(files: List[UploadFile] = File(...)):
    return {"filenames": [file.filename for file in files]}


@app.get("/")
async def main():
    content = """

""" return HTMLResponse(content=content) if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000, loop="asyncio")

 

form 与file

from fastapi import FastAPI, File, Form, UploadFile
import uvicorn

app = FastAPI()


@app.post("/files/")
async def create_file(
    file: bytes = File(...), fileb: UploadFile = File(...), token: str = Form(...)
):
    return {
        "file_size": len(file),
        "token": token,
        "fileb_content_type": fileb.content_type,
    }
if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000, loop="asyncio")

 

你可能感兴趣的:(Python)