在FastAPI中设置静态文件index.html(修复WebSocket聊天示例)


这是出现日历的第8天。日历是免费的!危险!
昨天我使用@ sh05_sh05的vim运行PDCA!

如何在FastAPI中放置静态文件。
要处理的代码使用官方文档的WebSocket示例。

这是Advent日历的狭窄主题,但是请把它作为Fast API的介绍以及WebSocket的大量聊天和文档。

由于这篇文章多余,因此如果要解决它并访问它,请跳到主要部分

什么是快速API?

Python的轻量级Web框架。辉煌等在其他页面和站点上有完整说明,因此在本文中

来自官方

  • 快速:极高的性能,可与NodeJS和Go媲美(感谢Starlette和Pydantic),这是目前最快的Python框架之一。
  • 快速编写代码:将功能开发的速度提高大约200%至300%。
  • 错误更少:减少约40%的人为错误(开发人员)。
  • 直观:强大的编辑器支持,随处可见,调试时间更少。
  • 简易:旨在易于使用和学习,减少阅读文档的时间。
  • 简短:减少代码重复。每个参数声明中的多个功能。更少的错误。
  • 健壮性:获得可用于生产环境的代码,并带有自动交互式文档。
  • 基于标准:基于API的开放标准(并与之完全兼容):OpenAPI(以前称为Swagger)和JSON Schema。

FastAPI

我将其引用为


我喜欢这样的事实,即文档是自动生成的,而且官方文档也很丰富。

处理代码

在此页面底部。
WebSockets --FastAPI

websocket_chat.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from typing import List

from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.responses import HTMLResponse

app = FastAPI()

### 割愛 ###

@app.websocket("/ws/{client_id}")
async def websocket_endpoint(websocket: WebSocket, client_id: int):
    await manager.connect(websocket)
    try:
        while True:
            data = await websocket.receive_text()
            await manager.send_personal_message(f"You wrote: {data}", websocket)
            await manager.broadcast(f"Client #{client_id} says: {data}")
    except WebSocketDisconnect:
        manager.disconnect(websocket)
        await manager.broadcast(f"Client #{client_id} left the chat")

如果直接移动它,则可以创建使用WebSocket的聊天应用程序。太奇妙了。

其中有两个类似的地方。

websocket_chat.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
html = """
<!DOCTYPE html>
<html>
    <head>
        Chat
    </head>
    <body>
        <h1>WebSocket Chat</h1>
        <h2>Your ID: <span id="ws-id"></span></h2>
        <form action="" onsubmit="sendMessage(event)">
            <input type="text" id="messageText" autocomplete="off"/>
            <button>Send</button>
        </form>
        <ul id='messages'>
        </ul>
        <script>
            var client_id = Date.now()
            document.querySelector("#ws-id").textContent = client_id;
            var ws = new WebSocket(`ws://localhost:8000/ws/${client_id}`);
            ws.onmessage = function(event) {
                var messages = document.getElementById('messages')
                var message = document.createElement('li')
                var content = document.createTextNode(event.data)
                message.appendChild(content)
                messages.appendChild(message)
            };
            function sendMessage(event) {
                var input = document.getElementById("messageText")
                ws.send(input.value)
                input.value = ''
                event.preventDefault()
            }
        </script>
    </body>
</html>
"""


@app.get("/")
async def get():
    return HTMLResponse(html)

似乎它显式声明了HTML并返回了一个字符串。
当然,该注释指出它不适用于生产环境,因此您应该与前台适当合作。

当我尝试使用它时,语法高亮显示不起作用(如果未设置),文件变长(如果禁用折叠)。

由于它是

,因此这次我们将放置FastAPI的静态文件,尤其是HTML。 (没有充分的理由,但我会作为一种实践)

阅读第

静态文件--FastAPI
看来您可以看到此页面,但是如果您阅读StarLette的文档(作为基础),则还有HTML的选项,因此请阅读(下面)。
顺便说一句,似乎响应者也基于Starlette。

静态文件--Starlette
如果您阅读此内容,请

html-以HTML模式运行。如果存在这样的文件,则自动为目录加载index.html。

。似乎index.html会像一个静态文件一样自动读取和访问。

主要故事

配置

1
2
3
4
app
├── html
│&nbsp;&nbsp; └── index.html
└── websocket_chat.py

安装aiofiles

1
pip install aiofiles

websocket_chat.py

1
2
3
4
5
6
7
8
9
10
11
from typing import List

from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.staticfiles import StaticFiles

app = FastAPI()


app.mount("/chat", StaticFiles(directory="/app/html", html=True), name="html")

# 以降は変更なし

app.mount是路由。
而且,由于如上所述,我指定读取index.html,因此无需添加@app.get就可以访问/chat
スクリーンショット 2020-12-08 17.17.15.png

结束