# '''stu = [ # {'sid':3,'name':'庞崽子','age':18,'sex':'女','address':'广东省深圳市龙岗区'}, # {'sid':1,'sex':'女','name':'pzz','age':20,'address':'广东省广州市'}, # {'sid':2,'name':'啊崽','sex':'男','age':30,'address':'广东省深圳市龙岗区'} # ] # # # 定义用户存储列表 # user_passwd = [] # # from fastapi import FastAPI,Query,Path,Body,Form,File,UploadFile # from pydantic import BaseModel,Field,HttpUrl # from typing import Optional,Union,Literal # from datetime import date,datetime # from uuid import UUID # # ap=FastAPI() # # @ap.get('/',summary='测试接口',tags=['测试用']) # def test(): # return '测试成功...' # # @ap.get('/students/{sid}',tags=['学生'],summary='学生信息查询接口',description='接口更加详细的解释说明...') # def get_students(sid:int = Path(ge=1,description='查询的id') ): # return [i for i in stu if i['sid'] == sid] # # # 定义请求体模型 # class Stu(BaseModel): # sid:int|None|str = 1 # name:str|None = Field(default='sz',min_length=2,max_length=50) # age:int = Field(default=0,ge=0,le=150,description='年龄属性') # sex:Literal['男','女'] # 限制sex属性只能是男、女 # address:str|None = None # birthday:date # url:HttpUrl # date_creat_date:datetime # # @ap.post('/students',tags=['学生'],summary='学生信息新增接口') # def add_students(s:Stu): # print( s ) # print(type(s)) # print('拿到类属性:',s.sid,s.name,s.address) # print('将请求体模型的所有类属性解析成字典:',s.model_dump()) # stu.append( s.model_dump() ) # return s # # class StuUpdate(BaseModel): # name:str|None = None # age:int = None # sex:Literal['男','女']|None = None # address:str|None = None # # @ap.put('/students/{sid}',tags=['学生'],summary='学生信息更新接口') # def update_students(sid:int,s:StuUpdate): # d = s.model_dump(exclude_unset=True) # print( d ) # exclude_unset=True 只解析前端输入的键值对,默认值不会解析 # for i in stu: # if i['sid'] == sid: # for k,v in d.items(): # i[k] = v # return {'code':200,'detail':'OK'} # # @ap.delete('/students/{sid}',tags=['学生'],summary='学生信息删除接口') # def delete_students(sid:int): # for i in stu: # if i['sid'] == sid: # stu.remove(i) # return {'code':200,'detail':'OK'} # # # 修改第二个新增接口,路径改成 /students/add 避免路由冲突 # @ap.post('/students/add',tags=['新增学生请求体'],summary='添加') # async def add_students2(stu:Stu): # print('请求体:',stu,type(stu)) # print('打印StuInfo的属性',stu.sid,stu.name,stu.age) # print('通过属性字典来查看:', stu.__dict__) # print('通过model_dump来解析成字典:',stu.model_dump(mode="json")) # return stu # # @ap.get('/users',tags=['用户信息']) # def get_students(user_passwd=None): # return user_passwd # # class User(BaseModel): # user:str # passwd:str # # # 用户注册,改成JSON方式,移除Form() # @ap.post('/users',tags=['用户注册']) # def user_register(user:User): # user_passwd.append({'user':user.user,'passwd':user.passwd}) # return {'code':200,'detail':'OK'} # @ap.post('/files1') # def add_file(f:bytes=File(...)): # print('打印二进制字符节:',f) # print('将二进制字节码成utf-8字符集:',f.decode('utf-8')) # with open('test.txt','wb') as file: # file.write(f) # @ap.post('/files2') # async def add_file(f:UploadFile): # print('uploadfile上传文件,读取该对象:',f) # print('文件名称:',f.filename) # text=await f.read() # print('读取的二进制字节内容:', text) # print('读取的正常字符内容:', text.decode('utf-8')) # with open(f.filename,'wb') as file: # file.write(text) # # if __name__ == '__main__': # import uvicorn # uvicorn.run("log:ap",host='127.0.0.1',port=12345) # ''' # 【day20作业】 # 把课上的笔记内容理清,再做下面的作业! from email.policy import default from idlelib.query import Query import datetime # import File # 1.阐述下你对restful规范的理解 '''①restful规范不是技术约束,而是一种开发习惯规范而已 ②restful面向资源开发,所以接口的路径名字要以资源的名字书写,见名知意,资源是复数时,要加上s代表单词是复数 ③restful规范不同方法的接口,定位不一样;''' # 2.什么是路径参数?查询参数? '''①路径参数:写在路径里面可变的变量参数!可以动态输入接收,用/students/{id} ②查询参数:用来查询获取资源的参数,在url里面是这么体现的:http://地址/路径?查询参数query''' # 3.get接口跟post接口有什么区别? '''①get接口是用来获取资源,接口可以直接在浏览器地址栏里访问,没有请求体 ②post接口是用来新增资源的,接口不能直接在浏览器地址栏访问,有请求体,请求体携带的数据不能直接看到''' # 4.Path() Query() Field() 三者的区别和用途 '''Path() 用来做路径参数的校验约束! Query() 用来做查询参数的校验约束! Field() 用来做请求体模型属性的校验约束!''' # 5.根据要求完成如下接口 # ①POST 接口 /login/{session_id},路径参数session_id要校验必须是字母跟数字组合,且长度要大于10字符 # ②请求体是个Form表单类型,属性包含:username(字符串 3-20 位,字母开头)、passwd(字符串 6-20 位)、is_ok(布尔) # ③功能函数还要有查询参数usertype,类型是 int # ④返回登录 username属性、usertype参数值、跟is_ok的json格式 '''from ai import FastAPI,Form,Path,Query ap=FastAPI() @ap.post('/login/{session_id}') async def login_session( session_id: str = Path(min_length=11, pattern='^[a-zA-Z0-9]+$'), username: str = Form(..., min_length=3, max_length=10, pattern='^[a-zA-Z].*'), password: str = Form(..., min_length=6, max_length=20), is_ok: bool = Form(), usertype: int = Query() ): print('返回的打印有:',session_id,username,is_ok,usertype) return {'username':username,'is_ok':is_ok,'usertype':usertype} if __name__ == '__main__': import uvicorn uvicorn.run("log:ap",host='127.0.0.1',port=12345)''' # 6.根据要求完成如下接口 # ①GET 接口 /users/{user_id} # ②user_id 必须 ≥ 1 # ③返回用户信息 '''@ap.get( '/users/{user_id}' ) async def get_users(user_id:int = Path(...,ge=1)): return {"user_id":user_id}''' # 7.创建商品的接口POST请求 # 需求: # ①商品名属性:2-50 字符, # ②价格属性:≥ 0 # ③库存属性:≥ 0 # ④分类属性:非空 # ⑤返回值是该商品的全部信息 '''from fastapi import FastAPI,Form,Path from pydantic import BaseModel from datetime import datetime,date ap=FastAPI() class Product(BaseModel): product_id:int=Path(min_length=2,max_length=50), product_price:float=Form(...,ge=0), product_num:str=Form(...,ge=0), product_type:str @ap.post( '/products' ) async def add_products(p:Product): return p if __name__ == '__main__': import uvicorn uvicorn.run("log:ap",host='127.0.0.1',port=12345)''' # 8.定义一个学生列表的全局变量 stu=[] 来存放学生信息,teac = [] 来存老师信息,老师跟学生的信息都是字典的形式存再列表里,要求完成以下接口需求 # ①定义一个请求体student模型,用来创建新增学生的信息到stu里,包含属性sid(int,默认值none)、sname(str)、age(默认值none,大于等于0)、sex(性别,只能是'男''女') # 、hobby(set类型,元素是str,多个爱好)、create_data(数据创建时间,datetime类),编写post请求的接口,传入数据,返回学生属性json '''from FastApi import FastAPI, Query from pydantic import BaseModel, Field from typing import Literal from datetime import datetime, date from enum import Enum Stu = [ {'sid': 3, 'sname': '庞崽子', 'age': 18, 'sex': '女', 'address': '广东省深圳市龙岗区'}, {'sid': 1, 'sname': 'pzz', 'age': 20, 'sex': '女', 'address': '广东省广州市'}, {'sid': 2, 'sname': '啊崽', 'age': 30, 'sex': '男', 'address': '广东省深圳市龙岗区'}, ] stu = [] # 新增学生存这里 teac = [] # 老师存这里 ap = FastAPI() from enum import Enum class SexEnum(str, Enum): f = '女' m = '男' class Student(BaseModel): sid: int | None = None sname: str = Field(..., min_length=1, max_length=20) age: int | None = Field(None, ge=0) sex: SexEnum | None = None hobby: set[str] create_date: date # ②基于stu学生列表查询,编写一个get请求,可以通过名字、性别(只能男或女)、 # 年龄(要有范围,0-120)来查询stu里的学生信息,返回值是查询命中的学生信息。如果没有任何的参数,那么就返回所有的学生信息 @ap.get('/',summary='测试接口',tags=['测试用']) def test(): return '测试成功...' @ap.post('/students') def add_students(s:Student): print(s.model_dump()) stu.append(s.model_dump()) @ap.get("/students") async def get_students( sname: str | None = None, sex: SexEnum | None = None, age: int |None= Query(default=None,ge=0,le=None), ): stu_tmp = [] for i in Stu: if sname and sname not in i["sname"]: continue if sex and i["sex"] != sex.value: continue if age is not None and i["age"] : continue stu_tmp.append(i) return stu_tmp # ③定义一个请求体teacher模型,用来创建添加老师信息的到teac列表里, # 有属性name(str或none)、salary(float)、hiredate(date 入职时间)、 # stu(使用如上的student类模型,嵌套,表示所带的学生),返回值是teac列表的所有信息 class teacher(BaseModel): sname:str|None=None salary:float hiredate:date stu:Student @ap.post('/teachers', summary='新增老师') async def add_teachers(t: teacher): teac.append(t.model_dump()) return teac if __name__ == '__main__': import uvicorn uvicorn.run("log:ap",host='127.0.0.1',port=12345)''' # 9.编写两个文件上传的接口 # ①利用bytes字节流类型上传文件,实现多文件上传,并将文件的内容保存到当前目录,保存的文件名字自定义 # ②利用uploadfile类型上传文件,实现多文件上传,并将文件保存到当前目录,文件名字原来叫什么名字,保存就叫什么名字 # ③总结下bytes跟uploadfile两种文件上传的区别 '''from fastapi import FastAPI, Query, UploadFile, File ap = FastAPI() @ap.post("/files/bytes") async def add_bytes_files(f:list[bytes]=File()): for i in range( len(f) ): print('解码 :',f[i].decode('utf-8') ) with open( f'第{i+1}个文件.txt','wb' ) as e: e.write(f[i]) return e @ap.post("/files/uploadfile") async def add_uploadfile(f:list[UploadFile]): print(f) for i in f: print('文件名字:',i.filename) text = await i.read() print( '文件的内容:',text.decode('utf-8') ) with open(i.filename,'wb') as ff: ff.write(text) return f if __name__ == '__main__': import uvicorn uvicorn.run("log:ap",host='127.0.0.1',port=12345)''' # 10.请总结下fastapi接口编写时,使用pydantic请求体模型的流程 '''①导入pydantic里的BaseModel基类 ②编写自定义的请求体模型,继承BaseModel基类 ③定义模型的类属性,使用Field()来约束校验属性的数据 ④引用时直接 形参:请求体模型'''