在上篇文章我们学习了FastAPI教程05——文件上传,这篇我们学习FastAPI教程06——响应类。

FastAPI提供了丰富的响应类来返回不同数据类型,常用的响应类如下表所示:

类型 用途
JSONResponse JSON数据,默认响应
HTMLResponse HTML内容
PlainTextResponse 纯文本
FileResponse 文件下载
StreamingResponse 流式响应
RedirectResponse 重定向

响应类位置

可以在装饰器中添加response_class参数指定响应类,一般用于HTML内容和纯文本,示例代码如下:

import uvicorn
from fastapi import FastAPI
from fastapi.responses import HTMLResponse

app = FastAPI()

# 在路由中设置响应类
@app.get("/html", response_class=HTMLResponse)  
async def read_html():
    return "<html><body><h1>Hello World</h1></body></html>"

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

运行结果如下:

在返回结果中指定响应类,示例代码如下:

from fastapi import FastAPI
from fastapi.responses import JSONResponse
import uvicorn

app = FastAPI()

@app.get("/response")
async def response():
    return JSONResponse(   # 指定响应类
        content={"message": "Hello"},
        status_code=200
    )

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

运行结果如下:

Json响应

Json响应是默认使用的响应,不需要指定响应类也可以,示例代码如下:

import uvicorn
from fastapi import FastAPI

app = FastAPI()

@app.get('/Dict')
async def get_dict():
    return {'name': '白巧克力', 'age': 18, 'hobby': ['唱', '跳', 'rap']}

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

运行结果如下图所示:

使用上面的方式返回JSON数据虽然是最简单的,但是在文档服务中的响应参考值为字符串,这样不利用开发人员了解我们的API接口。

Pydantic模型自动序列化

Pydantic模型自动序列化方式返回Json响应数据,功能更强大,可以在路由配置中添加参数,其语法格式如下:

@app.请求方法(
 '路由',
 response_model=数据类型类  # 数据结构和类型
 response_model_exclude_unset=True/False,  # 不返回不设置值的字段,默认为False
 response_model_exclude_defaults=True/False,  # 不返回是默认值的字段,默认为False
 response_model_exclude_none=True/False,   # 不返回是None的字段,默认为False
 response_model_include={ '字段1','字段2' },   # 返回字段
 response_model_exclude={ '字段1','字段2' },   # 不返回字段
)

示例代码如下:

import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class UserInfo(BaseModel):
    name: str
    age: int
    hobby: list[str] = []

@app.get('/Pydantic', response_model=UserInfo, response_model_exclude_unset=True)
async def get_pydantic():
    return {'name': '霖', 'age': 18}

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

运行结果如下:

当我们访问http://127.0.0.1:8004/Pydantic时,返回:

{
  "name": "霖",
  "age": 18
}

当把response_model_exclude_unset设置为False时,返回:

{
  "name": "霖",
  "age": 18,
  "hobby": []
}

HTML响应

HTMLResponse用于处理HTML格式的响应,其语法格式如下:

HTMLResponse(
    content = str,     # HTML内容
    status_code = int,  # 状态码
    headers = dict,    # 响应头
    media_type = 'text/html',     # 媒体类型
    background = 后台任务/None  # 后台任务
)

示例代码如下:

import uvicorn
from fastapi import FastAPI
from starlette.responses import HTMLResponse
app = FastAPI()

@app.get('/html1', response_class=HTMLResponse)
async def html1():
    return '<h1>装饰器</h1>'

@app.get('/html2')
async def html2():
    content = '<h1>返回结果</h1>'
    return HTMLResponse(
        content=content,
        status_code=200,
        headers={"X-Custom-Header": "CustomValue"},
        media_type="text/html"
    )

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

HTMLResponse会自动设置响应头的Content-Type为text/html; charset=utf-8,所以不需要设置Content-Type也可以。

文件响应

文件响应通常使用PlainTextResponse、FileResponse、StreamingResponse来实现,

PlainTextResponse

PlainTextResponse是用于处理纯文本格式的响应,其语法格式如下:

PlainTextResponse(
    content = str,     # HTML内容
    status_code = int,  # 状态码
    headers = dict,    # 响应头
    media_type = 'text/plain;charset=文本编码',     # 媒体类型
    background = 后台任务/None  # 后台任务
)

示例代码如下:

import uvicorn
from fastapi import FastAPI
from starlette.responses import PlainTextResponse

app = FastAPI()

@app.get('/text')
async def text():
    content = '白巧克力'
    return PlainTextResponse(
        content=content,
        status_code=200,
        headers={"X-Custom-Header": "CustomValue"},
        media_type="text/plain;charset=utf-8"
    )

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

运行结果如下:

FileResponse

FileResponse是用于处理文件下载和文件流传输,可以高效地传输文件,支持断点续传输和部分内容请求,其语法格式如下:

FileResponse(
    path = 文件路径,
    status_code = int/None,  # 状态码
    headers = dict/None,  # 自定义头部
    media_type= = 媒体类型/None,
    background = 后台任务/None,
    filename = 下载文件名,
    content_disposition_type = 内容处置类型,  # inline 内联显示,  attachment 直接下载
)

示例代码如下:

import uvicorn
from fastapi import FastAPI
from starlette.responses import FileResponse

app = FastAPI()

@app.get("/pdf")
async def download_pdf():
    file_Path = './file/myfile.pdf'
    return FileResponse(
        path=file_Path,  # 文件路径
        media_type="application/pdf",  # pdf文件
        filename='my.pdf',
        content_disposition_type='attachment'  # 直接下载
    )

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

运行结果如下:

点击下载即可下载文件。

也可以在请求头header中设置文件响应的一些配置,如:文件处理方式、下载后的文件名,示例代码如下:

@app.get("/pdf")
async def download_pdf():
    file_Path = './file/myfile.pdf'
    return FileResponse(
        path=file_Path,  # 文件路径
        media_type="application/pdf",  # 文本文件
        headers={
            'Content-Disposition': 'attachment; filename="my.pdf"',  # attachment: 直接下载 ,下载后文件名为mypdf.pdf
        }
    )

StreamingResponse

StreamingResponse用于流式传输数据的响应类,可以逐步生成和发送响应内容,而不是一次性发送所有数据。

StreamingResponse通常用于处理大文件、实时数据流或需要逐步生成的内容,其语法格式如下:

StreamingResponse(
    content = Any,  # 可迭代内容
    status_code = int,  # 状态码
    headers = dict,  # 自定义头部
    media_type = str,  # 媒体类型
    background = 后台任务
)

示例代码如下:

import uvicorn
from fastapi import FastAPI
from starlette.responses import StreamingResponse

app = FastAPI()

# 迭代函数
def generate_chunks(file_path: str, chunk_size: int = 1024 * 1024 * 10):
    with open(file_path, "rb") as f:
        while chunk := f.read(chunk_size):
            yield chunk

@app.get("/download_mp4")
async def download_pdf():
    file_Path = './file/会魔法的老人.mp3'
    return StreamingResponse(
        content=generate_chunks(file_Path),
        media_type="audio/mpeg",
        headers={
            'Content-Disposition': 'attachment; filename="my.mp3"',
        }
    )

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

重定向

RedirectResponse是用于重定向的响应类,可以让客户端跳转到另一个URL,其语法格式如下:

RedirectResponse(
    url = 目标URL,
    status_code = 307,  # 重定向状态码
    headers = dict,  # 自定义头部
    background = 后台任务
)

示例代码如下:

import uvicorn
from fastapi import FastAPI
from starlette.responses import RedirectResponse

app = FastAPI()

@app.get("/hello")
async def hello():
    return "Hello World!"

@app.get("/redirect")
async def redirect():
    return RedirectResponse("/hello")

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

运行结果如下:

mount挂载

mount用于挂载静态文件的方法,其语法格式如下:

app.mount(
    "/挂载路径",   
    StaticFiles(
        directory="目录路径",
        html=False,                  # 是否作为HTML文件服务
        check_dir=True,             # 检查目录是否存在
        follow_symlink=False,       # 是否跟随符号链接
        packages=None,              # 包内的静态文件
        encoding='文件编码'
    ),
    name="assets"  # 名称
)

示例代码如下:

import uvicorn
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

app = FastAPI()
app.mount("/static", StaticFiles(directory="static",html=False), name="static")

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

当我们想访问static目录下的requirements.txt资源时,可以访问http://127.0.0.1:8002/static/requirements.txt即可,如下图所示:

好了,FastAPI教程06——响应类就讲到这里了。

公众号:白巧克力LIN

该公众号发布Java、Python、数据库、Linux、Flask、FastAPI、Django、自动化测试、Git、算法、前端、服务器、AI等相关文章!

  • END -

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐