如何使用FastAPI获取Jinja2模板中更新的项目列表



我正在我的博客上构建一个评论系统,我正在呈现这样的现有评论:

{% for comment in comments %}
<div id="task-comments" class="pt-4">
<!--     comment-->
<div
class="bg-white rounded-lg p-3  flex flex-col justify-center items-center md:items-start shadow-lg mb-4">
<div class="flex flex-row justify-center mr-2">
<img alt="avatar" width="48" height="48"
class="rounded-full w-10 h-10 mr-4 shadow-lg mb-4"
src="https://cdn1.iconfinder.com/data/icons/technology-devices-2/100/Profile-512.png">
<h3 class="text-purple-600 font-semibold text-lg text-center md:text-left ">{{
comment.author['name']|e }}</h3>
</div>

<p style="width: 90%" class="text-gray-600 text-lg text-center md:text-left ">{{
comment.content|e }} </p>
</div>
<!--  comment end-->
<!--     comment-->
<!--  comment end-->
</div>
{% endfor %}

这里的问题是,当我发布评论(使用FastAPI路由(时,我不知道如何获得更新的评论列表。我知道Jinja可能不是最好的工具,并考虑过使用Alpine JS x-for循环,但我很想知道是否有一种方法可以在Jinja中实现这一点。

谢谢!!

这听起来像是WebSockets的一个用例。以下内容基于上面文档中给出的示例,可以处理多个连接,将新添加的注释广播给所有连接的客户端。因此,如果您打开http://127.0.0.1:8000/在浏览器的多个选项卡中,并使用其中一个连接添加新评论,其他每个选项卡也将收到新评论。如果您不想广播消息,那么您可以使用await manager.send_personal_message(data, websocket)

app.py

from fastapi import FastAPI, Request, WebSocket, WebSocketDisconnect
from fastapi.templating import Jinja2Templates
import uvicorn
class ConnectionManager:
def __init__(self):
self.active_connections: List[WebSocket] = []
async def connect(self, websocket: WebSocket):
await websocket.accept()
self.active_connections.append(websocket)
def disconnect(self, websocket: WebSocket):
self.active_connections.remove(websocket)
async def send_personal_message(self, message: str, websocket: WebSocket):
await websocket.send_json(message)
async def broadcast(self, message: str):
for connection in self.active_connections:
await connection.send_json(message)
class Comment:
def __init__(self, author, content): 
self.author = author 
self.content = content
app = FastAPI()
templates = Jinja2Templates(directory="templates")
manager = ConnectionManager()
comments = [] 
comments.append( Comment("author 1 ", "content 1") )
comments.append( Comment("author 2 ", "content 2") )
comments.append( Comment("author 3 ", "content 3") )
@app.get("/")
def main(request: Request):
return templates.TemplateResponse("index.html", {"request": request, "comments": comments})
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await manager.connect(websocket)
try:
while True:
data = await websocket.receive_json()
comments.append(Comment(data['author'], data['content']))
await manager.broadcast(data)
except WebSocketDisconnect:
manager.disconnect(websocket)

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

templates/index.html

<!DOCTYPE html>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Add new comment</h1>
<form action="" onsubmit="addComment(event)">
<input type="text" id="author" autocomplete="off"/>
<input type="text" id="content" autocomplete="off"/>
<button>Add comment</button>
</form>
<h2>Comments</h2>
<ul id='comments'>
{% for comment in comments %}
<li>
<h3> {{comment.author}} </h3>
<p> {{comment.content}} </p>
</li>
{% endfor %}
</ul>
<script>
var ws = new WebSocket("ws://localhost:8000/ws");
ws.onmessage = function(event) {
var comments = document.getElementById('comments')
var comment = document.createElement('li')
var jsonObj  = JSON.parse(event.data);
var authorNode = document.createElement('h3');
authorNode.innerHTML = jsonObj.author;
var contentNode = document.createElement('p');
contentNode.innerHTML = jsonObj.content;
comment.appendChild(authorNode);
comment.appendChild(contentNode);
comments.appendChild(comment)
};
function addComment(event) {
var author = document.getElementById("author")
var content = document.getElementById("content")
ws.send(JSON.stringify({"author": author.value, "content": content.value}))
author.value = ''
content.value = ''
event.preventDefault()
}
</script>
</body>
</html>

最新更新