【FastAPI】--基礎教程-CSDN博客
app.get和post的參數:
參數 | 類型 | 說明 |
---|---|---|
path | str | 路由路徑(如?"/marks" ),必填。 |
response_model | Type[T] | 定義響應數據的模型(如?percent ),會自動校驗和序列化輸出。 |
status_code | int | 自定義 HTTP 狀態碼(默認?200 ,成功創建可用?201 )。 |
tags | List[str] | 為 OpenAPI 分組(如?tags=["成績管理"] )。 |
summary | str | 接口的簡短描述。 |
description | str | 詳細說明(支持 Markdown)。 |
deprecated | bool | 標記接口為棄用(True ?時顯示為灰色)。 |
response_class | Response | 自定義響應類(如?JSONResponse 、HTMLResponse )。 |
responses | Dict | 擴展 OpenAPI 文檔,定義額外響應(如錯誤碼)。 |
目錄
1.FastAPI--模板
2.FastAPI--靜態文件
2.1.例子1
2.2.例子2
3.FastAPI--HTML 表單模板
4.FastAPI - 訪問表單數據
5.FastAPI - 上傳文件
6.FastAPI - Cookie 參數
7.FastAPI - Header 標頭參數
8.?FastAPI - Response 響應模型
9.FastAPI - 嵌套模型
10.?FastAPI - 依賴關系
1.FastAPI--模板
默認情況下,FastAPI 向客戶端呈現 JSON 響應。
但是如果我們需要返回前端網頁html應該如何操作?
可以將其轉換為 HTML 響應。
為此,FastAPI 在?fastapi.responses?模塊中定義了?HTMLResponse?類。
- 將?response_class?添加為操作裝飾器的附加參數,
- 將 HTMLResponse 對象作為其值。
from fastapi.responses import HTMLResponse
from fastapi import FastAPI
import uvicorn
app = FastAPI()
@app.get("/hello/")
async def hello():ret='''
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
'''return HTMLResponse(content=ret)if __name__ == "__main__":uvicorn.run(app='__main__:app', host='127.0.0.1', port=8000, reload=True)
請求 URL (http://localhost:8000/hello/) 也應該在瀏覽器中呈現消息。
另外一種方式:
Web 模板庫有一個模板引擎,可以合并一個帶有占位符變量的靜態網頁。 合并來自任何來源(例如數據庫)的數據以動態生成和呈現網頁。FastAPI 沒有任何預打包的模板庫。 因此,一個人可以自由使用適合他需要的任何一種模板庫。?
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from fastapi import FastAPI, Request# 創建FastAPI應用實例
app = FastAPI()# 初始化Jinja2模板引擎,指定模板文件存放的目錄為"templates"
templates = Jinja2Templates(directory="html")# 定義路由,指定路徑為"/hello/",并聲明返回類型為HTMLResponse
@app.get("/hello/", response_class=HTMLResponse)
async def hello(request: Request):"""處理/hello/路徑的GET請求參數:request: Request對象,包含HTTP請求信息返回:TemplateResponse: 渲染后的HTML模板響應"""# 使用模板引擎渲染hello.html模板# 第一個參數是模板文件名# 第二個參數是傳遞給模板的上下文字典,必須包含request對象return templates.TemplateResponse("gyp.html", {"request": request})
if __name__ == '__main__':import uvicornuvicorn.run(app='__main__:app', host='127.0.0.1', port=8000, reload=True)
項目結構樹:
project/
├── main.py
└── html/
????????└── gyp.html
?
?jinja2 模板允許將某些占位符嵌入到 HTML 代碼中。 jinja2 代碼元素放在大括號內。 一旦瀏覽器的 HTML 解析器遇到這種情況,模板引擎就會接管并使用 HTTP 響應提供的可變數據填充這些代碼元素。 Jinja2 提供以下代碼元素 ?
{% %}?– 聲明
{{ }}?– 打印到模板輸出的表達式
{# #}?? 未包含在模板輸出中的注釋
# # #?? 行語句
hello.html?修改如下,通過替換名稱參數來顯示動態消息。
<html lang="en"><body>
<h2>Hello {{name}} Welcome to FastAPI</h2>
</body>
</html>
操作函數hello()也被修改為接受name作為路徑參數。?TemplateResponse?還應的括。?"name":name?的 JSON 表示以及請求上下文
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from fastapi import FastAPI, Request# 創建FastAPI應用實例
app = FastAPI()# 初始化Jinja2模板引擎,指定模板文件存放的目錄為"templates"
templates = Jinja2Templates(directory="html")# 定義路由,指定路徑為"/hello/",并聲明返回類型為HTMLResponse
@app.get("/hello/{name}", response_class=HTMLResponse)
async def hello(request: Request, name: str):"""處理/hello/路徑的GET請求參數:request: Request對象,包含HTTP請求信息返回:TemplateResponse: 渲染后的HTML模板響應"""# 使用模板引擎渲染hello.html模板# 第一個參數是模板文件名# 第二個參數是傳遞給模板的上下文字典,必須包含request對象return templates.TemplateResponse("test.html", {"request": request, "name": name})
if __name__ == '__main__':import uvicornuvicorn.run(app='__main__:app', host='127.0.0.1', port=8000, reload=True)
2.FastAPI--靜態文件
經常需要在模板響應中包含一些資源,這些資源即使有一定的動態數據也保持不變。 此類資源稱為靜態資源。 媒體文件(.png、.jpg 等)、用于執行某些前端代碼的 JavaScript 文件或用于格式化 HTML 的樣式表(.CSS 文件)都是靜態文件的示例。
為了處理靜態文件,您需要一個名為aiofiles?的庫
app.mount("/static", StaticFiles(directory="static"), name="static")
??
"/static"
??
- 訪問路徑前綴,比如?
http://yourdomain.com/static/style.css
?會映射到本地?./static/style.css
?文件。??
StaticFiles(directory="static")
??
- 指定靜態文件存放的目錄(這里是項目根目錄下的?
static
?文件夾)。??
name="static"
??
- 可選參數,用于標識這個掛載點(OpenAPI 文檔或調試時有用)。
2.1.例子1
在下面的示例中,FastAPI 徽標將在 hello.html 模板中呈現。 因此,"fa-logo.png"文件首先放在靜態文件夾中。 它現在可用作 HTML 代碼中?<img>?標記的?src?屬性。
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
import uvicorn
app = FastAPI()
templates = Jinja2Templates(directory="html")app.mount("/static", StaticFiles(directory="html/static"), name="static")
@app.get("/hello/{name}", response_class=HTMLResponse)async def hello(request: Request, name:str):return templates.TemplateResponse("hello.html", {"request": request, "name":name})if __name__ == "__main__":uvicorn.run(app='__main__:app', host='127.0.0.1', port=8000, reload=True)
hello.html:
<html><body><h2>Hello {{name}} Welcome to FastAPI</h2><img src="{{ url_for('static', path='fa-logo.png') }}" alt="" width="300"></body>
</html>
</pre>
2.2.例子2
這是靜態文件的另一個例子。 JavaScript 代碼 hello.js 包含?myfunction()?的定義,該定義將在以下 HTML 腳本 (\templates\hello.html) 中的?onload?事件上執行。
<html><head><title>My Website</title><script src="{{ url_for('static', path='hello.js') }}"></script></head><body onload="myFunction()"><div id="time" style="text-align:right; width="100%"></div><h1><div id="ttl">{{ name }}</div></h1></body>
</html>
hello.js代碼如下 ??(\static\hello.js)
function myFunction() {var today = new Date();var h = today.getHours();var m = today.getMinutes();var s = today.getSeconds();var msg="";if (h<12) {msg="早上好, ";}if (h>=12 && h<18) {msg="下午好, ";}if (h>=18) {msg="晚上好, ";}var x=document.getElementById('ttl').innerHTML;document.getElementById('ttl').innerHTML = msg+x;document.getElementById('time').innerHTML = h + ":" + m + ":" + s;
}
該函數檢測當前時間的值,并根據一天中的時間將適當的值分配給?msg?變量(早上好、下午好或晚上好)。
3.FastAPI--HTML 表單模板
讓我們向我們的應用程序添加另一個路由?"/login"?,它呈現一個具有簡單登錄表單的 html 模板。 登錄頁面的HTML代碼如下 。
<html><body><form action="/submit" method="POST"><h3>Enter User name</h3><p><input type='text' name='nm'/></p><h3>Enter Password</h3><p><input type='password' name='pwd'/></p><p><input type='submit' value='Login'/></p></form></body>
</html>
請注意,action 參數設置為"/submit"路由,method 設置為 POST。 這對于進一步討論具有重要意義。
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
import uvicorn
app = FastAPI()
templates = Jinja2Templates(directory="./login")@app.get("/hello", response_class=HTMLResponse)async def hello(request: Request):return templates.TemplateResponse("login.html", {"request": request})if __name__ == "__main__":uvicorn.run(app='__main__:app', host='127.0.0.1', port=8000, reload=True)
4.FastAPI - 訪問表單數據
下面我們將看到如何在 FastAPI 操作函數中訪問 HTML 表單數據。 在上面的示例中,/login 路由呈現了一個登錄表單。 用戶輸入的數據以 POST 為請求方式提交到?/submit?URL。 現在我們必須提供一個視圖函數來處理用戶提交的數據。
FastAPI 有一個 Form 類來處理通過提交 HTML 表單作為請求接收到的數據。 但是,您需要安裝?python-multipart?模塊。 它是一個用于 Python 的流式部分表單解析器。
pip3 install python-multipart
讓我們定義一個?submit()?函數,由@app.post() 修飾。 為了接收表單數據,聲明兩個 Form 類型的參數,與表單屬性同名。
from fastapi import FastAPI, Request
from fastapi import Form
import uvicorn
app = FastAPI()@app.post("/submit/")
async def submit(nm: str = Form(...), pwd: str = Form(...)):return {"username": nm}if __name__ == "__main__":uvicorn.run(app='__main__:app', host='127.0.0.1', port=8000, reload=True)
甚至可以使用 HTML 表單數據填充和返回 Pydantic 模型。 在下面的代碼中,我們將 User 類聲明為 Pydantic 模型并將其對象作為服務器的響應發送。
from pydantic import BaseModel
class User(BaseModel):username:strpassword:str
@app.post("/submit/", response_model=User)
async def submit(nm: str = Form(...), pwd: str = Form(...)):return User(username=nm, password=pwd)
5.FastAPI - 上傳文件
<html><body><form action="http://localhost:8000/uploader" method="POST" enctype="multipart/form-data"><input type="file" name="file" /><input type="submit"/></form></body>
</html>
首先,要將文件發送到服務器,您需要設置 HTML 表單的 enctype 為?multipart/form-data,并使用 input 輸入類型為 file 來呈現按鈕, 單擊時允許您從文件系統中選擇一個文件。
請注意,表單的 action 參數到端點 http://localhost:8000/uploader 并且 method 設置為 POST。
通過fastapi:
from fastapi import FastAPI, File, UploadFile, Request
import uvicorn
import shutil
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templatesapp = FastAPI()
templates = Jinja2Templates(directory="templates")@app.get("/upload/", response_class=HTMLResponse)
async def upload(request: Request):return templates.TemplateResponse("上傳文件.html", {"request": request})@app.post("/uploader/") # 定義POST請求路由,處理文件上傳到/uploader/路徑
async def create_upload_file(file: UploadFile = File(...)): # 接收上傳文件,file參數是UploadFile類型,File(...)表示必填with open("destination.png", "wb") as buffer: # 以二進制寫入模式打開/創建destination.png文件shutil.copyfileobj(file.file, buffer) # 將上傳文件內容復制到目標文件return {"filename": file.filename} # 返回JSON響應,包含原始文件名if __name__ == "__main__":uvicorn.run(app='__main__:app', host='127.0.0.1', port=8000, reload=True)
6.FastAPI - Cookie 參數
cookie?是 HTTP 標頭之一。 Web 服務器向客戶端發送響應,除了請求的數據外,它還會插入一個或多個 cookie。?cookie?是存儲在客戶機器中的非常少量的數據。 在同一客戶端的后續連接請求中,此 cookie 數據也隨 HTTP 請求一起附加。
cookie 可用于記錄有關客戶瀏覽的信息。 Cookie 是通過 HTTP 協議在無狀態通信中檢索有狀態信息的可靠方法。
在 FastAPI 中,通過?set_cookie()?方法在 response 響應對象上設置 cookie 參數
response.set_cookie(key, value)
這里是?set_cookie()?方法的一個例子。 我們有一個名為 content 的 JSON 響應對象。 調用?set_cookie()?方法將 cookie 設置為?key="usrname"?和?value="admin"??
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from fastapi import FastAPI, Cookie
app = FastAPI()
@app.post("/cookie/")
def create_cookie():content = {"message": "cookie set"}response = JSONResponse(content=content)response.set_cookie(key="username", value="admin")return response
@app.get("/readcookie/")
async def read_cookie(username: str = Cookie(None)):return {"username": username}if __name__ == "__main__":import uvicornuvicorn.run(app='__main__:app', host='127.0.0.1', port=8000, reload=True)
當執行read_cookie()?函數時,cookie 會被讀回并作為響應出現。
7.FastAPI - Header 標頭參數
為了讀取作為客戶端請求的一部分的?HTTP header?標頭的值,從 FastAPI 庫中導入 Header 對象,并在操作函數定義中聲明一個 Header 類型的參數。參數的名稱應與以?camel_case?轉換的 HTTP 標頭相匹配。
在以下示例中,將檢索"accept-language"標頭。 由于 Python 不允許在標識符名稱中使用"-"(破折號),因此將其替換為"_"(下劃線)
from typing import Optional
from fastapi import FastAPI, Header
from fastapi.responses import JSONResponse
app = FastAPI()@app.get("/headers/")
async def read_header(accept_language: Optional[str] = Header(None)):return {"Accept-Language": accept_language}@app.get("/rspheader/")
def set_rsp_headers():content = {"message": "Hello World"}headers = {"X-Web-Framework": "FastAPI", "Content-Language": "en-US"}return JSONResponse(content=content, headers=headers)if __name__ == "__main__":import uvicornuvicorn.run(app='__main__:app', host='127.0.0.1', port=8000, reload=True)
檢索到的標頭顯示為響應正文。
您可以在響應對象中推送自定義和預定義的標頭。操作函數應該有一個Response類型的參數。 為了設置自定義標頭,其名稱應以"X"?為前綴。在以下情況下,將添加一個名為"X-Web-Framework"的自定義標頭和一個預定義標頭"Content-Language"以及操作功能的響應。
新添加的標頭將出現在文檔的響應標頭部分。
8.?FastAPI - Response 響應模型
一個操作函數向客戶端返回一個 JSON 響應。 響應可以是 Python 主要類型的形式,即數字、字符串、列表或字典等。它也可以是 Pydantic 模型的形式。 對于返回模型對象的函數,操作裝飾器應該聲明一個?respone_model?參數。
在 response_model 的幫助下,FastAPI 將輸出數據轉換為模型類的結構。 它在 OpenAPI 路徑操作中驗證數據,為響應添加 JSON 模式。
response_model 參數的一個重要優點是,我們可以通過從模型中選擇字段來格式化輸出,從而將響應轉換為輸出模型。
from typing import List
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class student(BaseModel):id: intname :str = Field(None, title="name of student", max_length=10)marks: List[int] = []percent_marks: float
class percent(BaseModel):id:intname :str = Field(None, title="name of student", max_length=10)percent_marks: float
@app.post("/marks", response_model=percent)
async def get_percent(s1:student):s1.percent_marks=sum(s1.marks)/2return s1
POST 操作裝飾器以 student 學生類(BaseModel 的子類)對象的形式接收請求主體。 作為此類中的一個字段,即響應中不需要 marks(標記列表),我們定義了另一個名為 percent 的模型,并將其用作 response_model 參數。
9.FastAPI - 嵌套模型
Pydantic?模型的每個屬性都有一個類型。 類型可以是內置的 Python 類型或模型本身。 因此,可以使用特定的屬性名稱、類型和驗證來聲明嵌套的 JSON"對象"。
示例
在下面的示例中,我們構建了一個客戶模型,其中一個屬性作為產品模型類。 反過來,產品模型具有供應商類屬性。
from typing import Tuple
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class supplier(BaseModel):supplierID:intsupplierName:str
class product(BaseModel):productID:intprodname:strprice:intsupp:supplier
class customer(BaseModel):custID:intcustname:strprod:Tuple[product]@app.post('/invoice')
async def getInvoice(c1:customer):return c1if __name__ == "__main__":import uvicornuvicorn.run(app='__main__:app', host='127.0.0.1', port=8000, reload=True)
10.?FastAPI - 依賴關系
FastAPI 內置的依賴注入系統使得在構建 API 時集成組件變得更加容易。 在編程中,依賴注入是指一個對象接收它所依賴的其他對象的機制。 其他對象稱為依賴項。 依賴注入有以下優點 ?
重復使用相同的共享邏輯
共享數據庫連接
實施身份驗證和安全功能
假設一個FastAPI應用程序有兩個操作函數,都具有相同的查詢參數id、name和age。
from fastapi import FastAPI
app = FastAPI()
@app.get("/user/")
async def user(id: str, name: str, age: int):return {"id": id, "name": name, "age": age}
@app.get("/admin/")
async def admin(id: str, name: str, age: int):return {"id": id, "name": name, "age": age}
如果有任何更改,例如添加/刪除查詢參數,則路由裝飾器和函數都需要更改。
FastAPI 提供了Depends?類,它的對象在這種情況下用作公共參數。 首先從 FastAPI 導入?Depends?并定義一個函數來接收這些參數 ?
async def dependency(id: str, name: str, age: int):return {"id": id, "name": name, "age": age}@app.get("/user/")
async def user(dep: dict = Depends(dependency)):return dep
對于每一個新的Request,FastAPI使用對應的參數調用依賴函數,返回結果,并將結果賦值給你的操作。
您可以使用類而不是函數來管理依賴項。 聲明一個具有 id、name 和 age 作為屬性的類。
class dependency:def __init__(self, id: str, name: str, age: int):self.id = idself.name = nameself.age = age
使用這個類作為參數的類型。
@app.get("/user/")
async def user(dep: dependency = Depends(dependency)):return dep
@app.get("/admin/")
async def admin(dep: dependency = Depends(dependency)):return dep
里,我們在操作函數中使用了依賴注入。 它也可以用作操作裝飾。 例如,我們要檢查查詢參數 age 的值是否小于 21。如果是,則應拋出異常。 因此,我們編寫一個函數來檢查它并將其用作依賴項。
async def validate(dep: dependency = Depends(dependency)):if dep.age > 18:raise HTTPException(status_code=400, detail="You are not eligible")
@app.get("/user/", dependencies=[Depends(validate)])
async def user():return {"message": "You are eligible"}
在 FastAPI 依賴管理中,可以使用 yield 代替 return 來增加一些額外的步驟。 例如,以下函數使用帶有 yield 的數據庫依賴項。
async def get_db():db = DBSession()try:yield dbfinally:db.close()