一、安装和基本运行访问
官方示例代码
from typing import Union from fastapi import FastAPI app = FastAPI() @app.get("/") def read_root(): return {"Hello": "World"} @app.get("/items/{item_id}") def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q}
运行命令:uvicorn test:app --reload
注意:运行命令app前面那个是文件位置,官方的文件名叫main,要以实际的文件名为准,不然找不到app
二、post请求和json参数嵌套
1、post请求 写法一:一层参数
class Hero(BaseModel): q:str w:str e:str # 可以为不传这个自动也可以传字符串,不传这个字段时该字段默认值为None r:Union[str, None] = None @app.post('/ya_suo') def ya_suo(hero:Hero): print(hero.r) #取值 if hero.r==None: return '大招都没有' return hero
测试无r参数情况
测试有r参数情况
2、post请求 写法二:参数嵌套
2.1、错误写法
@app.post('/ti_mo') def ti_mo(q:str,w:str,e:str,r:Union[str, None] = None): a={"q技能":q,"w技能":w,"e技能":e,"r技能":r} return a
报错了
2.2、正确写法
这样才行q:str,这种只用于路径参数,因为r可以为空或者不写,可以不用是路径参数
@app.post('/ti_mo1/{cd}') def ti_mo1(cd:str,r:Union[str, None] = None): a={"技能cd":str(cd)+'s',"r技能":r} return a
@app.post('/ti_mo1/{cd}') def ti_mo1(cd:str,r:Union[str, None] = None): a={"技能cd":str(cd)+'s',"r技能":r} return a
2.3、嵌套多个请求参数(不明白的话看下面的postman的请求参数就懂了)
#这2个就直接用官方写的了 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.post('/q_t/{id}') def q_t(id:int,item:Item,user:User): return {'id':id,'item':item,'user':user}
2.4、嵌套单个请求参数(细节max)(不明白的话看下面的postman的请求参数就懂了~)
#只有嵌套单个请求体的话请求参数和多个是有很大区别的 @app.post('/q_t1/{id}') def q_t1(id:int,user:User): return {'id':id,'user':user}
注意:重点在发起请求的时候
希望请求参数格式
{ "user": { "username": "dave", "full_name": "Dave Grohl" } }
可是现在会报错
要这样才会成功,可是这不是我们想要的结果
按照官方的解决办法,在我这有点问题
告诉我确实一个参数(可能版本有啥问题把)
缺少我就先补上这个参数试试,发现就能正常使用了
@app.post('/q_t1/{id}') def q_t1(id:int,user:User= Body(...,embed=True)): return {'id':id,'user':user}
最终测试
三、请求体 - 字段Field
#字段Field class Item(BaseModel): name: str description: Union[str, None] = Field( default='默认值', title="这是一个商品", max_length=300 ) price: float = Field(gt=0, description="商品价格必须大于0") tax: Union[float, None] = None @app.post("/items/{item_id}") def update_item(item_id: int, item: Item = Body(...,embed=True)): results = {"item_id": item_id, "item": item} return results
gt=0的意思,看源码字段的解释
测试商品价格小于等于0的情况
测试正常情况
四、请求参数字段使用字典列表集合嵌套
#请求参数字段使用字典列表集合嵌套 class Image(BaseModel): #检查是否为有效的url url: HttpUrl name: str class Item(BaseModel): name: str # 参数格式:字符串或者为空不传这个字段 description: Union[str, None] = None price: float # 参数格式:小数或者为空不传这个字段 tax: Union[float, None] = None tags: Set[str] = set() #参数格式:列表里面包含字典或者为空不传这个字段 images: Union[List[Image], None] = None @app.post('/qtt/{id}') def qtt(id:int,item:Item): return {"id": id, "item": item}
字段设置说明
测试结果和请求参数:使用 tags: Set[str] = set(),我重复的写了一个"metal",,被去重了,列表嵌套字典
五、返回结果限制返回字段
#创建一个有明文密码的输入模型和一个没有明文密码的输出模型,让密码不返回 class UserRequest(BaseModel): username: str password: str class UserResponse(BaseModel): username: str #response_model=UserResponse 设置返回模型的字段,返回结果会过滤掉未在输出模型中声明的字段数据 @app.post("/user", response_model=UserResponse) def create_user(user: UserRequest): #只会返回username信息 return user
返回模型的字段不能出现请求模型字段没有的字段
测试,没有返回密码字段
六、异常信息处理
#基本使用异常信息 e=[1,2,4,5,6,9] @app.get('/err/{id}') def err(id:int): if id not in e: raise HTTPException(status_code=404,detail='id不存在') return {'id':id}
输入id为3,不存在的结果
输入id为1,存在的结果
七、接口文档
八、全局依赖设置全局token,name在header里面校验,获取header的信息作为变量使用
from fastapi import Depends, FastAPI, Header, HTTPException #token: str = Header(...) header信息使用 def verify_token(token: str = Header(...)): if token != "em123dca": raise HTTPException(status_code=400, detail="Token 无效") #方法名字没啥要求 def name(name: str = Header(...)): if name != "lcf": raise HTTPException(status_code=400, detail="该用户没有权限访问") #全局依赖 app = FastAPI(dependencies=[Depends(verify_token), Depends(name)]) @app.get("/header_token") #可以这样获取header的信息(做一些token信息解析),应该有其他方法的,没找到,谁找到告诉我一下 def get_token(name: str = Header(...),token: str = Header(...)): return {'name':name,'token':token}
测试:正确的token和有权限的name
测试:正确的token和无权限的name
测试:错误的token和有权限的name
都错误的话先校验token的,因为方法写在前面
九、启动服务器的第二种方式,让同局域网下用户可以访问
查询下自己的局域网ip地址
python查询ip地址
cmd查询ip地址
from fastapi import FastAPI app = FastAPI() @app.get("/") def s(): return '局域网测试12' if __name__ == '__main__': import uvicorn uvicorn.run(app='test2:app',host='192.168.11.177',port=8001, reload=True)
测试
优化下启动代码
#!/usr/bin/env python # -*- coding: utf-8 -*- ''' @time : 2022/6/21 @Author : LL @File : test2.py ''' from fastapi import FastAPI def get_ip(): import socket res = socket.gethostbyname(socket.gethostname()) return res app = FastAPI() @app.get("/") def s(): return '局域网测试12' if __name__ == '__main__': import uvicorn #app='test2:app' 文件位置:app uvicorn.run(app='test2:app',host=get_ip(),port=8001, reload=True)