Skip to content

Commit b388c96

Browse files
committed
第四章 响应处理和FastAPI配置
1 parent b7f2685 commit b388c96

File tree

1 file changed

+149
-70
lines changed

1 file changed

+149
-70
lines changed

tutorial/chapter04.py

Lines changed: 149 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -2,73 +2,152 @@
22
# -*- coding:utf-8 -*-
33
# __author__ = '__Jack__'
44

5-
# from typing import List
6-
#
7-
# from fastapi import Form, File, UploadFile
8-
# from starlette.requests import Request
9-
#
10-
# from fastapi import APIRouter
11-
#
12-
#
13-
# app02 = APIRouter()
14-
#
15-
#
16-
# @app02.post("/user/")
17-
# async def login_post(request: Request, username: str = Form(...), password: str = Form(...)):
18-
# """
19-
# Form表单操作
20-
# :param request:
21-
# :param username:
22-
# :param password:
23-
# :return:
24-
# """
25-
#
26-
# print(f"username: {username}, password: {password}")
27-
#
28-
# return templates.TemplateResponse("post.html", {"request": request, "username": username, "password": password})
29-
#
30-
#
31-
# @app02.get("/user/")
32-
# async def login_get(request: Request):
33-
# return templates.TemplateResponse("post.html", {"request": request})
34-
#
35-
#
36-
# @app02.get("/file/")
37-
# async def login_get(request: Request):
38-
# return templates.TemplateResponse("file.html", {"request": request})
39-
#
40-
#
41-
# @app02.post("/file/")
42-
# async def upload_file(request: Request, files_list: List[bytes] = File(...), files_name: List[UploadFile] = File(...)):
43-
# """
44-
# 上传多个文件
45-
# :param request:
46-
# :param files_list: List[bytes]表示可上传多个文件,bytes表示上传一个文件
47-
# :param files_name:
48-
# :return:
49-
# """
50-
#
51-
# return templates.TemplateResponse("file.html", {
52-
# "request": Request,
53-
# "file_sizes": [len(file) for file in files_list], # 用字节长度表示文件大小
54-
# "filenames": [file.filename for file in files_name]
55-
# })
56-
#
57-
#
58-
# @app02.post("/create_file/")
59-
# async def create_file(request: Request, file1: bytes = File(...), file2: UploadFile = File(...), notes: str = Form(...)):
60-
# """
61-
# 上传单个文件
62-
# :param request:
63-
# :param file1: bytes类型可以统计长度,但是没有content_type属性
64-
# :param file2: UploadFile类有content_type属性,但是不能len()统计文件长度
65-
# :param notes:
66-
# :return:
67-
# """
68-
#
69-
# return templates.TemplateResponse("file.html", {
70-
# "request": Request,
71-
# "file_size": len(file1),
72-
# "notes": notes,
73-
# "file2_content_type": file2.content_type
74-
# })
5+
from typing import Optional, List
6+
7+
from fastapi import APIRouter, status, Form, File, UploadFile, HTTPException
8+
from pydantic import BaseModel, EmailStr
9+
10+
app04 = APIRouter()
11+
12+
"""Response Model 响应模型"""
13+
14+
15+
class UserIn(BaseModel):
16+
username: str
17+
password: str
18+
email: EmailStr
19+
mobile: str = "10086"
20+
address: str = None
21+
full_name: Optional[str] = None
22+
23+
24+
class UserOut(BaseModel):
25+
username: str
26+
email: EmailStr # 用 EmailStr 需要 pip install pydantic[email]
27+
mobile: str = "10086"
28+
address: str = None
29+
full_name: Optional[str] = None
30+
31+
32+
users = {
33+
"user01": {"username": "user01", "password": "123123", "email": "[email protected]"},
34+
"user02": {"username": "user02", "password": "123456", "email": "[email protected]", "mobile": "110"}
35+
}
36+
37+
38+
@app04.post("/response_model/", response_model=UserOut, response_model_exclude_unset=True)
39+
async def response_model(user: UserIn):
40+
"""response_model_exclude_unset=True表示默认值不包含在响应中,仅包含实际给的值,如果实际给的值与默认值相同也会包含在响应中"""
41+
print(user.password) # password不会被返回
42+
# return user
43+
return users["user01"]
44+
45+
46+
@app04.post(
47+
"/response_model/attributes",
48+
response_model=UserOut,
49+
# response_model=Union[UserIn, UserOut],
50+
# response_model=List[UserOut],
51+
response_model_include=["username", "email", "mobile"],
52+
response_model_exclude=["mobile"]
53+
)
54+
async def response_model_attributes(user: UserIn):
55+
"""response_model_include列出需要在返回结果中包含的字段;response_model_exclude列出需要在返回结果中排除的字段"""
56+
# del user.password # Union[UserIn, UserOut]后,删除password属性也能返回成功
57+
return user
58+
# return [user, user]
59+
60+
61+
"""Response Status Code 响应状态码"""
62+
63+
64+
@app04.post("/status_code", status_code=200)
65+
async def status_code():
66+
return {"status_code": 200}
67+
68+
69+
@app04.post("/status_attribute", status_code=status.HTTP_200_OK)
70+
async def status_attribute():
71+
print(type(status.HTTP_200_OK))
72+
return {"status_code": status.HTTP_200_OK}
73+
74+
75+
"""Form Data 表单数据处理"""
76+
77+
78+
@app04.post("/login/")
79+
async def login(username: str = Form(...), password: str = Form(...)): # 定义表单参数
80+
"""用Form类需要pip install python-multipart; Form类的元数据和校验方法类似Body/Query/Path/Cookie"""
81+
return {"username": username}
82+
83+
84+
"""Request Files 单文件、多文件上传及参数详解"""
85+
86+
87+
@app04.post("/file")
88+
async def file_(file: bytes = File(...)): # 如果要上传多个文件 files: List[bytes] = File(...)
89+
"""使用File类 文件内容会以bytes的形式读入内存 适合于上传小文件"""
90+
return {"file_size": len(file)}
91+
92+
93+
@app04.post("/upload_files")
94+
async def upload_files(files: List[UploadFile] = File(...)): # 如果要上传单个文件 file: UploadFile = File(...)
95+
"""
96+
使用UploadFile类的优势:
97+
1.文件存储在内存中,使用的内存达到阈值后,将被保存在磁盘中
98+
2.适合于图片、视频大文件
99+
3.可以获取上传的文件的元数据,如文件名,创建时间等
100+
4.有文件对象的异步接口
101+
5.上传的文件是Python文件对象,可以使用write(), read(), seek(), close()操作
102+
"""
103+
for file in files:
104+
contents = await file.read()
105+
print(contents)
106+
return {"filename": files[0].filename, "content_type": files[0].content_type}
107+
108+
109+
"""【见coronavirus应用】
110+
开发COVID-19感染数据查询接口
111+
FastAPI项目的静态文件配置
112+
Jinja2模板渲染COVID-19查询页面
113+
"""
114+
115+
"""Path Operation Configuration 路径操作配置"""
116+
117+
118+
@app04.post(
119+
"/path_operation_configuration",
120+
response_model=UserOut,
121+
# tags=["Path", "Operation", "Configuration"],
122+
summary="This is summary",
123+
description="This is description",
124+
response_description="This is response description",
125+
deprecated=True,
126+
status_code=status.HTTP_200_OK
127+
)
128+
async def path_operation_configuration(user: UserIn):
129+
"""
130+
Path Operation Configuration 路径操作配置
131+
:param user: 用户信息
132+
:return: 返回结果
133+
"""
134+
return user.dict()
135+
136+
137+
"""【见run.py】FastAPI 应用的常见配置项"""
138+
139+
"""Handling Errors 错误处理"""
140+
141+
142+
@app04.get("/http_exception")
143+
async def http_exception(city: str):
144+
if city != "Beijing":
145+
raise HTTPException(status_code=404, detail="City not found!", headers={"X-Error": "Error"})
146+
return {"city": city}
147+
148+
149+
@app04.get("/http_exception/{city_id}")
150+
async def override_http_exception(city_id: int):
151+
if city_id == 1:
152+
raise HTTPException(status_code=418, detail="Nope! I don't like 1.")
153+
return {"city_id": city_id}

0 commit comments

Comments
 (0)