当前位置:   article > 正文

13.FastAPI Response对象

fastapi response

13.FastAPI Response对象

在某些情况下,可能会需要对请求返回特定的数据,而不是采用默认的方式,此时,就可以直接使用Response对象。在FastAPI中,可以在路由操作函数声明一个fastapi.Response类型的参数,然后在函数的代码直接操作Response对象。

13.1更改响应状态码

可以在路由操作函数中,通过对Response对象的 status_code 赋值来修改响应状态码,代码如下:

from fastapi import FastAPI
from fastapi import Response
from fastapi import status
​
app = FastAPI()
​
@app.get(path='/hello', status_code=status.HTTP_200_OK)
async def hello(response: Response):
    response.status_code = status.HTTP_201_CREATED
    return {'hello': 'world'}

执行请求后后台日志输出:

127.0.0.1:50876 - "GET /hello HTTP/1.1" 201 Created

在上面的代码中,虽然在装饰器中使用参数设置为返回状态码为200,但在函数中可以通过Response对象对返回状态码进行修改。

13.2JSON编码器

在某些情况下,可能需要在 Pydantic模型与Python类型之间进行转换,目的是将数据转换为与JSON兼容的数据结构,比如:list、dict等。FastAPI提供 jsonable_encoder()函数来支持这样的数据转换。该函数接受一个Pydantic模型对象作为参数,返回一个对应的JSON兼容版本。

代码如下:

from fastapi import FastAPI
from pydantic import BaseModel
from datetime import datetime
from datetime import time
from fastapi.encoders import jsonable_encoder
​
app = FastAPI()
​
class Task(BaseModel):
    name: str
    created: datetime
    runat: time
    creator: str
​
@app.get(path='/test')
async def test():
    task = Task(name='hello', created=datetime.now(), runat=time(hour=2,minute=30,second=0), creator='admin')
    print(type(task))
    enjson = jsonable_encoder(task)
    print(type(enjson))
    print(enjson)
    return task

执行请求:

curl http://127.0.0.1:8000/test
{
    "name":"hello",
    "created":"2022-01-15T09:17:16.061638",
    "runat":"02:30:00",
    "creator":"admin"
}

后台print输出:

<class 'main2.Task'>
<class 'dict'>
{'name': 'hello', 'created': '2022-01-15T09:17:16.061638', 'runat': '02:30:00', 'creator': 'admin'}

从上面的代码及代码执行结果可以看出: 代码将 Pydantic 模型转换为一个字典,其值与JSON兼容,并将这个datetime和time转换为一个字符串。

事实上,在FastAPI内部是使用jsonable_encoder来转换数据的。

13.3 直接返回Response对象

13.3.1 JSONResponse

在前面的代码中,当创建一个FastAPI路由时,可以返回dict、list、Pydantic 模型等,那么FastAPI内部是如何处理的呢?FastAPI默认会使用 jsonable_encoder 将返回值转换为JSON格式, 然后,FastAPI 会在后台将这些兼容 JSON 的数据(比如字典)放到一个 JSONResponse 中,该 JSONResponse 会用来发送响应给客户端。

JSONResponse 是Response 的子类,Response 还有很多子类,在后面的内容中介绍。

13.3.2返回 Response

实际上,可以直接返回Response或其任何子类,当直接返回Response时,FastAPI会直接传递它,FastAPI 不会用 Pydantic 模型做任何数据转换,不会将响应内容转换成任何类型。这种特性带来了极大的可扩展性,可以返回任何数据类型,重写任何数据声明或者校验等。

在下面的代码中,我们通过JSONResponse 人为返回我们希望返回的内容,代码如下:

from fastapi import FastAPI
from pydantic import BaseModel
from datetime import datetime
from datetime import time
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse
​
app = FastAPI()
​
class Task(BaseModel):
    name: str
    created: datetime
    runat: time
    creator: str
​
@app.get(path='/test')
async def test():
    task = Task(name='hello', created=datetime.now(), runat=time(hour=2,minute=30,second=0), creator='admin')
    jTask = jsonable_encoder(task)
    return JSONResponse(content=jTask)

执行请求:

curl http://127.0.0.1:8000/test
{"name":"hello","created":"2022-01-15T10:53:33.009967","runat":"02:30:00","creator":"admin"}

13.4Response

在FastAPI中,Response接受如下参数:

  • content

    str 或者 bytes。

  • status_code

    int 类型的 HTTP 状态码。

  • headers

    由字符串组成的 dict。

  • media_type

    给出媒体类型的 str,比如 "text/html"。

可以直接返回Response,示例代码如下:

from fastapi import FastAPI
from fastapi import Response
​
app = FastAPI()
​
@app.get(path='/test')
async def test():
    data = '''<?xml version="1.0"?>
    <shampoo>
        <Header>
            Apply shampoo here.
        </Header>
        <Body>
            You'll have to use soap here.
        </Body>
    </shampoo>
    '''
    return Response(content=data, media_type="application/xml")

执行请求:

curl http://127.0.0.1:8000/test
<?xml version="1.0"?>
    <shampoo>
        <Header>
            Apply shampoo here.
        </Header>
        <Body>
            You'll have to use soap here.
        </Body>
    </shampoo>

13.5Response子类

  • HTMLResponse

    接受文本或字节并返回 HTML 响应。

  • PlainTextResponse

    接受文本或字节并返回纯文本响应。

  • JSONResponse

    接受数据并返回一个 application/json 编码的响应,是 FastAPI 中使用的默认响应。

  • ORJSONResponse

    ORJSONResponse 是一个使用orjson的快速的可选 JSON 响应。

  • UJSONResponse

    UJSONResponse 是一个使用 ujson的可选 JSON 响应。

  • RedirectResponse

    返回 HTTP 重定向。默认情况下使用 307 状态代码(临时重定向)。

  • StreamingResponse

    采用异步生成器或普通生成器/迭代器,然后流式传输响应主体。

  • FileResponse

    异步传输文件作为响应。

使用这些子类的方法:

  1. 可以在路径操作装饰器中通过 response_class 参数声明想要返回的 Response

  2. 路由操作函数中将返回的内容将被放在对应的Response中 , 如果该 Response 有一个 JSON 媒体类型(application/json),比如使用 JSONResponse 或者 UJSONResponse 的时候,返回的数据将使用在路径操作装饰器中声明的任何 Pydantic 的 response_model 自动转换(和过滤)。

13.5.1ORJSONResponse

ORJSONResponse在性能上有所提高,使用ORJSONResponse需要安装orjson,执行:

pip install orjson

代码如下:

from fastapi import FastAPI
from pydantic import BaseModel
from datetime import datetime
from datetime import time
from fastapi.responses import ORJSONResponse

app = FastAPI()

class Task(BaseModel):
    name: str
    created: datetime
    runat: time
    creator: str


@app.get(path='/test', response_class=ORJSONResponse)
async def test():
    task = Task(name='hello', created=datetime.now(), runat=time(hour=2,minute=30,second=0), creator='admin')
    return task

13.5.2 HTMLResponse

代码如下:

from fastapi import FastAPI
from fastapi.responses import HTMLResponse

app = FastAPI()

@app.get(path='/test')
async def test():
    data = '''
    <html>
        <head>
            <title>Some HTML in here</title>
        </head>
        <body>
            <h1>Look ma! HTML!</h1>
        </body>
    </html>
    '''
    return HTMLResponse(content=data)

上面的代码没有使用response_class 参数,而是直接返回相应的HTMLResponse。

13.5.3PlainTextResponse

代码如下:

from fastapi import FastAPI
from fastapi.responses import PlainTextResponse

app = FastAPI()

@app.get(path='/test', response_class=PlainTextResponse)
async def test():
    data = 'Hello FastAPI!!!'
    return data

13.5.4UJSONResponse

在处理某些边缘情况时,ujson 不如 Python 的内置实现那么谨慎。需要安装ujson

pip install ujson

代码如下:

from fastapi import FastAPI
from pydantic import BaseModel
from datetime import datetime
from datetime import time
from fastapi.responses import UJSONResponse

app = FastAPI()

class Task(BaseModel):
    name: str
    created: datetime
    runat: time
    creator: str

@app.get(path='/test', response_class=UJSONResponse)
async def test():
    task = Task(name='hello', created=datetime.now(), runat=time(hour=2,minute=30,second=0), creator='admin')
    return task

13.5.5RedirectResponse

代码如下:

from fastapi import FastAPI
from fastapi.responses import RedirectResponse

app = FastAPI()

@app.get(path='/test')
async def test():
    return RedirectResponse("https://www.baidu.com")

13.5.6StreamingResponse

代码如下:

from fastapi import FastAPI
from fastapi.responses import StreamingResponse

app = FastAPI()

@app.get(path='/test')
async def test():
    async def read_data():
        for i in range(10):
            data = 'hello fastapi {0} \r\n'.format(i)
            yield data
    return StreamingResponse(content=read_data())

执行请求:

curl http://127.0.0.1:8000/test
hello fastapi 0
hello fastapi 1
hello fastapi 2
hello fastapi 3
hello fastapi 4
hello fastapi 5
hello fastapi 6
hello fastapi 7
hello fastapi 8
hello fastapi 9

使用StreamingResponse实现流式下载文件,代码如下:

from fastapi import FastAPI
from fastapi.responses import StreamingResponse

app = FastAPI()

@app.get(path='/test')
async def test():
    def read_file():
        with open('Apache_OpenOffice_4.1.11_Win_x86_install_en-US.exe', 'rb') as f:
            yield from f

    return StreamingResponse(content=read_file())

当使用浏览器访问http://127.0.0.1:8000/test时开始下载文件。

13.5.7FileResponse

该响应接受不同的参数进行实例化:

  • path

    要流式传输的文件的文件路径。

  • headers

    任何自定义响应头,传入字典类型。

  • media_type

    给出媒体类型的字符串。如果未设置,则文件名或路径将用于推断媒体类型。

  • filename

    如果给出,它将包含在响应的 Content-Disposition 中。

代码如下:

from fastapi import FastAPI
from fastapi.responses import FileResponse

app = FastAPI()

@app.get(path='/test')
async def test():
    return FileResponse(path='Apache_OpenOffice_4.1.11_Win_x86_install_en-US.exe')

当使用浏览器访问http://127.0.0.1:8000/test时开始下载文件。

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/416380
推荐阅读
相关标签
  

闽ICP备14008679号