admin管理员组

文章数量:1561891

fastapi——快速入门笔记

根据慕课网视频教程
地址:https://www.bilibili/video/BV1iN411X72b?p=36

print("\033[31m5. --- ORM模型: 从类创建符合的ORM对象模型   ---\033[Om")#显示彩色内容

fastapi是高性能的web框架。他的主要特点是:
快速编码
减少人为bug
直观
简易
具有交互式文档
基于API的开放标准(并与之完全兼容):OpenAPI(以前称为Swagger)和JSON Schema。

1.1fastapi的安装

一、fastapi的安装

pip install fastapi

当然你可以使用国内阿里云镜像源进行安装,会快很多,上面的语句变成下面的:

pip install fastapi -i https://mirrors.aliyun/pypi/simple

因为fastapi启动依赖于uvicorn,所以我们还需要安装uvicorn

pip install uvicorn -i https://mirrors.aliyun/pypi/simple

到这里,fastapi就安装完毕了,下面我们来验证一下安装是否成功

1-2、验证是否安装成功

新建名字叫main.py的文件,将下面内容复制到里面去

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

然后使用终端开启uvicorn服务

uvicorn main:app --reload

uvicorn main:app 命令指:

main: main.py 文件(也可理解为Python模块).
app: main.py 中app = FastAPI()语句创建的app对象.
--reload: 在代码改变后重启服务器,只能在开发的时候使用

你将会看到如下的输出:

INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [8438] using statreload
INFO:     Started server process [8440]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

然后打开浏览器,输入: http://127.0.0.1:8000。看看有没有打印出:"message": "Hello World" 这句话,如果有,表示安装成功。

如果你此时访问 http://127.0.0.1:8000/docs。你将会看到自动生成的API交互文档。这点很重要,也是fastapi的一个优点。

1.2.2fastapi项目启动时,提示ERROR

fastapi项目启动时,提示ERROR: Error loading ASGI app. Could not import module “main”.

文件名为 f1.py

代码如下:

from fastapi import FastAPI  # 导入FastAPI
import uvicorn

app = FastAPI()  # 创建一个app实例


@app.get("/")  # 编写一个路径操作装饰器
async def root():  # 编写一个路径操作函数
    return {
   "你好!": "朋友。"}


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

注意:声明app的文件路径应该是 f1:app,而不是main:app。

只需将 app=‘main:app’ 改为app='f1:app’即可。

结束!

1.3fastapi固定开头

# -*- codeing = utf-8 -*-
# @time : 2021/5/7 23:57
# @file : main.py.PY
# @Author : 夜羽
from fastapi import FastAPI  # 导入FastAPI
#from fastapi import APIRouter         #接口路由
import uvicorn       # 运行fastapi
'''内容选填
app = FastAPI()  # 创建一个app实例           
#app01 = APIRouter()

@app.get("/")  # 编写一个路径操作装饰器
async def root():  # 编写一个路径操作函数
    return {"你好!": "朋友。123"}
'''

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True,  workers=1)
    
    # workers=1进程数量

main: main.py 文件(也可理解为Python模块).
app: main.py 中app = FastAPI()语句创建的app对象.
--reload: 在代码改变后重启服务器,只能在开发的时候使用

debug: 修改代码后不必再运行一次程序,保存后可直接运行

另一种方法

导入运行文件名在一个程序文件中:

from .chapter03 import app03
from .chapter04 import app04
from .chapter05 import app05
from .文件名 import app实例名

后只用一个程序运行多个:

from fastapi import FastAPI
import uvicorn   #运行fastapi
from fastapi知识点教程 import app03     导入app实例名称项目
from fastapi知识点教程 import app04
from fastapi知识点教程 import app05
#from 上层文件夹名称 import app实例名


app = FastAPI()


#prefix=  路径    tags=[]  名称
app.include_router(app03, prefix='/chapter03', tags=['第三章 请求参数和验证'])
app.include_router(app04, prefix='/chapter04', tags=['第四章 响应处理和fastapi设置'])
app.include_router(app05, prefix='/chapter05', tags=['第五章 fastapi的依赖注入系统'])


if __name__ == '__main__':
    uvicorn.run('RUN:app', host="127.0.0.1", port=8000, reload=True, debug=True, workers=1)
#woker=1进程数量

1.4代码练习

from typing import List, Optional        #Optional 参数可以为空或已经声明的类型

app = FastAPI()  # 创建一个app实例

class Cityinfo(BaseModel):
    province: str
    country: str
    is_affectse: Optional[bool] = None

@app.get("/")  # 编写一个路径操作装饰器
def root():  # 编写一个路径操作函数
    return {
   "你好!": "朋友。23"}

#@app.get("/city/{city}?q=xx")  # 编写一个路径操作装饰器   q=xx 查询参数
@app.get("/city/{city}")
async def result(city: str,query: Optional[str] = None): # 编写一个路径操作函数
    return {
   "city": city, "query": query}

if __name__ == '__main__':
    uvicorn.run(app='web1:app', host="127.0.0.1", port=8000, reload=True, debug=True)
# -*- codeing = utf-8 -*-
# @time : 2021/5/6 22:55
# @file : pydantic.PY
# @Author : 夜羽
# @Software : PyCharm
#导入库时一定要注意大小写
from pydantic import BaseModel, ValidationError  #可在运行时提供代码类型提示,报错是提供较为友好的错误提示
from datetime import datetime, date
from pathlib import Path         #新建Path文件
from typing import List, Optional        #Optional 参数可以为空或已经声明的类型

from sqlalchemy import Column, Integer, String     #列,征型,字符类型
from sqlalchemy.dialects.postgresql import array  #元祖
from sqlalchemy.ext.declarative import declarative_base     #声明



class user(BaseModel):
    id: int
    name: str = "john snow"     #默认值
    signup_ts: Optional[datetime] = None      #Optional 参数可以为空或已经声明的类型
    friends: list[int] = []    #列表中元素是int类型或者是可以直接转化为int 类型的值

date = {
   
    "id" : "123456",
    "name" : 'nima',
    "signup_ts" : datetime.today(),#现在的时间
    "friends" :[1,'2',3]
}
user = user(**date)  # **的作用是收集关键字参数到一个新的字典,并将整个字典赋值给字典_date
print(user.id,user.name)  #实例化后调用属性
print(user.json())    #字典形式打开
print(user.id)          #实例化后调用属性
print(user.dict())       #字典形式打开
print(user.schema())
print(user.schema_json())     #会提示使用的数据格式类型
print(user.__fields__.keys())     #查看定义的类型,所有的字段都表明类就不会乱


"""
Path = Path('pydanti.json')         #新建一个jsom文件
Path.write_text('{"id" : "123456","name" : "nima","signup_ts" : datetime.today(),friends" :[1,"2",3]}')
print(user.parse_file(Path))     #解析文件 parse_解析

#写入内容 write_text写入

#现在的时间"


User_data = {'{"id" : "123","name" : "nima","signup_ts" : datetime.today(),friends" :[1,"2",3]}'}
print(user.construct(**User_data))
"""

class sound(BaseModel):
    sound: str

class dog(BaseModel):
    birthday: Optional[datetime] = None
    weight: float = Optional[None]
    sound: List[sound]             # 不同的叫声. 递归模型,就是指一个嵌套一个


dogs = dog(birthday=datetime.today(), weight=6.66, sound=[{
   "sound": "wangwagn"}, {
   "sound": "yingying"}])
print(dogs.dict())


print("\033[31m5. --- ORM模型: 从类创建符合的ORM对象模型   ---\033[Om")

Base = declarative_base()  #声明性基础

class companyorm(Base):
from fastapi import APIRouter, Path       #APIRouter  api路由器, Path   路径校验
from enum import Enum          # 枚举

app03 = APIRouter()

@app03.get("/path/parametrs")
def path01():
    return {
   "message": "this is a message"}

@app03.get("/path/{parametrs}")        # 函数的顺序就是路由的顺序
def path01(parametrs: str):
    return {
   "message": parametrs}

class cityname(str,Enum):           #枚举参数类型, 使用后可以选填下方参数
    beijing = "beijing China"
    shanghai = "shanghai China"

@app03.get("/enum/{city}")                #枚举参数类型
async def latest(city: cityname):
    if city == cityname.shanghai:
        return {
   'city_name': city, "确诊数量": 123, "死亡": 0}
    if city == cityname.beijing:
        return {
   'city_name': city, "确诊数量": 1231, "死亡": 0}
    return {
   "city_name": city, "latest": "unknown"}



@app03.get("/files/{flie_path: path}")      # 路径参数path parameters传递文件路径
def fliepath(flie_path: str):
    return f"the file path is {flie_path}"            #传递数据

 # Path(None) 可为空 ,title="这是一个标题", description="描述", ge=1,le=10 大于1小于10
@app03.get("/path_1/{unm}")
def path03(
        #num: int =Path(None, title="这是一个标题", description="描述",ge=1,le=10)
        unm: int = Path(..., title="这是一个标题", description="描述", ge=1, le=10)
):
    return unm

run运行文件

# -*- coding = utf-8 -*-
# @Time : 2021/5/10 10:18
# @File : RUN.PY
# @Author : 夜羽
# @Software: PyCharm
import time
from fastapi import FastAPI, Request, Request
from fastapi.middleware.cors import CORSMiddleware  #跨域资源共享
from fastapi.templating import Jinja2Templates   #模板渲染网页
import uvicorn   #运行fastapi
from fastapi知识点教程 import app03
from fastapi知识点教程 import app04
from fastapi知识点教程 import app05
from fastapi知识点教程 import app06
from fastapi知识点教程 import app07
from fastapi知识点教程 import app08
#from coronavirus import application

from fastapi.staticfiles import StaticFiles             #静态文件

#应用常见配置
app = FastAPI(
    title='FastAPI 学习和 练习用的 API Docs',    #标题
    description='FastAPI教程 学习练习api,学习视频:https://www.bilibili/video/BV1iN411X72b  老师github库:https://github/liaogx/fastapi-tutorial',     #描述
    version='1.0.0',           #版本号
    docs_url='/docs',       #路由地址
    redoc_url='/redocs',   #重置地址
)
app.mount(path="/static", app=StaticFiles(directory="./static"), name="static")   #静态文件配置    # .mount()不要在分路由APIRouter().mount()调用,模板会报错

#拦截所有的请求     middleware中间键
@app.middleware('http')
async def add_process_time_header(request: Request, call_next):  # call_next将接收request请求做为参数
    start_time = time.time()
    response = await call_next(request)
    process_time = time.time() - start_time
    response.headers['X-Process-Time'] = str(process_time)  # 添加自定义的以“X-”开头的请求头
    return response


# 跨域资源共享
app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "http://127.0.0.1",
        "http://127.0.0.1:8080"
    ],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)






#prefix=  路径    tags=[]  名称
app.include_router(app03, prefix='/chapter03', tags=['第三章 请求参数和验证'])
app.include_router(app04, prefix='/chapter04', tags=['第四章 响应处理和fastapi设置'])
app.include_router(app05, prefix='/chapter05', tags=['第五章 fastapi的依赖注入系统'])
app.include_router(app06, prefix='/chapter06', tags=['第六章 fastapi的安全、认证和授权'])
app.include_router(app07, prefix='/chapter07', tags=['第七章 fastapi的数据库操作和多应用的目录结构设计'])
app.include_router(app08, prefix='/chapter08', tags=['第八章 中间键\跨域资源共享\后台任务\测试用例'])
#app.include_router(application, prefix='/chapter07', tags=['新冠病毒疫情跟踪器'])



if __name__ == '__main__':
    uvicorn.run('RUN:app', host="127.0.0.1", port=8000, reload=True, debug=True, workers=1)
#woker=1进程数量

在一个文件中实现

@app.get("/11", tags=["渲染界面"],
    responses={
   403: {
   "description": "Operation forbidden"}},)
async def root():
    return {
   "message": "Hello World"}

@app.get("/12", tags=["渲染界面1"],
    responses={
   403: {
   "description": "Operation forbidden"}},)
async def root():
    return {
   "message": "Hello World"}

@app.get("/13", tags=["渲染界面2"],
    responses={
   403: {
   "description": "Operation forbidden"}},)
async def root():
    return {
   "message": "Hello World"}

api备注

Path(None) 可为空 ,title=“这是一个标题”, description=“描述”, ge=1,le=10 大于1小于10, alias=‘别名’ #convert_underscores=True 转换为无下划线

default=[“默认值”],

值类型列子

def cookie(user_agent: Optional[str] = Header(None, convert_underscores=True, description="描述"),
        x_token: List[str] = Header(None, description="描述")):
    
    unm: int = Path(..., title="这是一个标题", description="描述", ge=1, le=10)
#查询:    
values: list[str] = Query(default=["v1","v2"], alias='alias_name', title="这是一个标题", description="描述",)
@app03.get("/path_1/{unm}")
def path03(
    values: list[str] = Query(default=["v1","v2"], alias='alias_name', title="这是一个标题", description="描述",),
    unm: int = Path(..., title="这是一个标题", description="描述", ge=1, le=10)
        #num: int =Path(None, title="这是一个标题", description="描述",ge=1,le=10)

api属性备注

“”"

备注内容

“”"

print("\033[31m5. --- cookkie 和 header   ---\033[Om")#

@app03.get("/header")         #不需要使用cookie
def cookie(user_agent: Optional[str] = Header(None, convert_underscores=True, description="XIANXI"), x_token: List[str] = Header(None, description="描述")):    #convert_underscores=True  转换为无下划线
    """
    有些http代理和服务器是不支持在请求中带有下划线的,convert_underscores=True转换为无下划线
    :param user_agent: convert_underscores=True
    :param x_token: 包含多个值得列表
    :return:    返还定义的属性
    """
    return {
   "user_agent": user_agent, "x_token": x_token}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9wLZRynr-1631113988190)(C:\Users\gouguoxiong\Desktop\py后端\批注 2021-05-10.jpg)]

枚举(可选型)

from enum import Enum 

class cityname(str,Enum):           #枚举参数类型, 使用后可以选填下方参数
    beijing = "beijing China"
    shanghai = "shanghai China"

子应用

#应用常见配置
app = FastAPI(
    title='FastAPI Tutorial and Coronavirus Tracker API Docs',    #标题
    description='FastAPI教程 新冠病毒疫情跟踪器API接口文档,项目代码:https://github/liaogx/fastapi-tutorial',     #描述
    version='1.0.0',           #版本号
    docs_url='/docs',       #路由地址
    redoc_url='/redocs',   #重置地址

1.5api交互文档

可以写入内容

http://127.0.0.1:8000/docs

只显示不可更改

FastAPI - ReDoc

查询参数

1、查询参数概念(前端传递的数据给后端校验)

#多查询参数的列表,参数别名alias

Query

当你声明不属于路径参数的其他函数参数时,它们将自动解释为“Query”参数,也就是查询参数。

查询参数就是一系列在URL?之后的key-value键值对,每对键值对用 & 分割开来。例如

http://127.0.0.1:8000/items/?skip=0&limit=10

查询参数有两个,一个是skip,一个是limit,它们的值分别为0,10

由于它们都是URL的一部分,所以 “本质上” 它们都是字符串。

但是当你需要使用Python类型来声明query参数的时候(例如用int),他们就会被转换为相应的类型并且依据这个类型来验证传入参数。

适用于Path参数的所有过程也适用于Query参数

  • 编辑器支持
  • 数据解析
  • 数据验证
  • 自动文档
from fastapi import APIRouter, Path, Query      #APIRouter  api路由器, Path   路径校验   Query 查询
from enum import Enum          # 枚举
from typing import List, Optional        #Optional 参数可以为空或已经声明的类型

print("\033[31m5. --- 查询参数, 和字符串验证   ---\033[Om")#


@app03.get("/quety")
def page_limit(page: int = 1 , limit: Optional[int] = None):
    if limit:
        return {
   "page":page, "limit": limit}
    return {
   "page": page,}


@app03.get("/quety/bool/conversion")
def type_conversion(param: bool = False):
    return param

@app03.post("/piery/validations")
def que(
        value: str = Query(...,min_length=8, max_length=20, regex="^a"),
        values: list[str] = Query(default=["v1","v2"], alias='alias_name')
):     #多查询参数的列表,参数别名alias
    return values, value

2.请求体和字段

当您需要将数据从客户端(例如浏览器)发送到API时,可以将其作为 “请求体” 发送。

请求体是客户端发送到您的API的数据。 响应体是您的API发送给客户端的数据。

API几乎总是必须发送一个响应体,但是客户端并不需要一直发送请求体。

定义请求体,需要使用 Pydantic 模型。注意以下几点

  • 不能通过GET请求发送请求体

  • 发送请求体数据,必须使用以下几种方法之一:POST(最常见)、PUT、DELETE、PATCH如何实现请求体

  • 当想实现全部接口的请求时:

    @app.api_route("/api", methods=("GET", "POST", "PUT"))
    async def api():
        return {"api": "GET, POST, PUT"}
    
实现请求体总共包含三个步骤。

第一步,从`pydantic`中导入`BaseModel`

```
from pydantic import BaseModel
```

第二步,创建请求体数据模型

声明请求体数据模型为一个类,且该类继承 BaseModel。所有的属性都用标准Python类。和查询参数一样:数据类型的属性如果不是必须的话,可以拥有一个默认值或者是可选None。否则,该属性就是必须的。

例如,声明了一个`JSON`对象

```python
from pydantic import BaseModel

class Item(BaseModel):
    name: str 
    description: str = None
    price: float 
    tax: float = None 
```

所以访问链接的时候传入的请求体可以是下面两种,

```python
{
    "name": "Foo",
    "description": "An optional description",
    "price": 45.2,
    "tax": 3.5
}
```

另一种可以不传递默认值或者是可选值,(注意字典后面最后一个元素不需要逗号)

```python
{
    "name": "Foo",
    "price": 45.2
}
```

第三步、将模型定义为参数

将上面定义的模型添加到你的路径操作中,就和定义Path和Query参数一样的方式:

```python
from fastapi import FastAPI
from pydantic import BaseModel


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


app = FastAPI()


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

声明参数的类型为你创建的模型 Item

这样当你使用postman选择post方法访问链接并传递一个值为

{
“name”: “Foo”,
“price”: 45.2
}

的请求体之后,会得到输出

{
“name”: “Foo”,
“price”: 45.2
}

3.cookie 和 header

安装postpai

使用:

cookie

print("\033[31m5. --- cookkie 和 header   ---\033[Om")#

@app03.get("/cookie")         #效果需要使用cookie
def cookie(cookie_id: Optional[str] = Cookie(None)):    #使用cookie参数来定义cookie类
    return {
   "coookie_id": cookie_id}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OWgQIWJX-1631113988192)(C:\Users\gouguoxiong\Desktop\py后端\批注 2021-05-10 22222.jpg)]

header

print("\033[31m5. --- cookkie 和 header   ---\033[Om")#

@app03.get("/header")         #不需要使用cookie
def cookie(user_agent: Optional[str] = Header(None, convert_underscores=True, description="XIANXI"), x_token: List[str] = Header(None, description="描述")):    #convert_underscores=True  转换为无下划线
    """
    有些http代理和服务器是不支持在请求中带有下划线的,convert_underscores=True转换为无下划线
    :param user_agent: convert_underscores=True
    :param x_token: 包含多个值得列表
    :return:    返还定义的属性
    """
    return {
   "user_agent": user_agent, "x_token": x_token}

响应数据进行规范和校验

1.响应模型类

#请求和响应的区别:返回响应不会返回密码

from pydantic import BaseModel, EmailStr   #检验

本文标签: 入门快速简单FastAPI