[英]Dynamic updates in real time to a django template
我正在構建一個將提供實時數據的Django應用。 我是Django的新手,現在我專注於如何實時更新數據,而不必重新加載整個頁面。
需要澄清的一點是:實時數據應該定期更新,而不僅僅是通過用戶輸入。
視圖
def home(request):
symbol = "BTCUSDT"
tst = client.get_ticker(symbol=symbol)
test = tst['lastPrice']
context={"test":test}
return render(request,
"main/home.html", context
)
模板
<h3> var: {{test}} </h3>
我已經問過這個問題,但是我有一些疑問:
有人告訴我使用Ajax,沒關系,但是Ajax是否適合這種情況?我會在該頁面中加載每x秒實時更新的數據的頁面嗎?
我也被告知要使用DRF(Django Rest Framework)。 我一直在仔細研究它,但是對我來說尚不清楚的是它在這種情況下如何工作。
在下面的內容中,我提供了一個清單,該清單列出了實現Websocket和Django Channels解決方案所需的操作,如上一條注釋中所建議。 最后給出了動機。
在客戶端上,您需要執行以下javascript代碼:
<script language="javascript">
var ws_url = 'ws://' + window.location.host + '/ws/ticks/';
var ticksSocket = new WebSocket(ws_url);
ticksSocket.onmessage = function(event) {
var data = JSON.parse(event.data);
console.log('data', data);
// do whatever required with received data ...
};
</script>
在這里,我們打開Websocket,然后在onmessage
回調中詳細說明服務器發送的通知。
可能的改進:
<script language="javascript">
var prefix = (window.location.protocol == 'https:') ? 'wss://' : 'ws://';
var ws_url = prefix + window.location.host + '/ws/ticks/';
var ticksSocket = new ReconnectingWebSocket(ws_url);
...
</script>
要配置Django頻道,請按照以下說明進行操作:
https://channels.readthedocs.io/en/latest/installation.html
Channel Layers是Django Channels的可選組件,它提供了“組”抽象,我們將在以后使用; 您可以按照此處給出的說明進行操作:
https://channels.readthedocs.io/zh-CN/latest/topics/channel_layers.html#
路由為Websocket(和其他協議)提供了已發布的終結點與關聯的服務器端代碼之間的映射,就像urlpattens在傳統Django項目中為HTTP所做的一樣
文件routing.py
from django.urls import path
from channels.routing import ProtocolTypeRouter, URLRouter
from . import consumers
application = ProtocolTypeRouter({
"websocket": URLRouter([
path("ws/ticks/", consumers.TicksSyncConsumer),
]),
})
消費者是一個類,它為Websocket標准(以及可能的自定義)事件提供處理程序。 從某種意義上說,它對Websocket的作用類似於Django視圖對HTTP的作用。
在我們的情況下:
文件consumers.py
:
from django.conf import settings
from asgiref.sync import async_to_sync
from channels.consumer import SyncConsumer
class TicksSyncConsumer(SyncConsumer):
def websocket_connect(self, event):
self.send({
'type': 'websocket.accept'
})
# Join ticks group
async_to_sync(self.channel_layer.group_add)(
settings.TICKS_GROUP_NAME,
self.channel_name
)
def websocket_disconnect(self, event):
# Leave ticks group
async_to_sync(self.channel_layer.group_discard)(
settings.TICKS_GROUP_NAME,
self.channel_name
)
def new_ticks(self, event):
self.send({
'type': 'websocket.send',
'text': event['content'],
})
例如:
ticks = [
{'symbol': 'BTCUSDT', 'lastPrice': 1234, ...},
...
]
broadcast_ticks(ticks)
哪里:
import json
from asgiref.sync import async_to_sync
import channels.layers
def broadcast_ticks(ticks):
channel_layer = channels.layers.get_channel_layer()
async_to_sync(channel_layer.group_send)(
settings.TICKS_GROUP_NAME, {
"type": 'new_ticks',
"content": json.dumps(ticks),
})
我們需要group_send()
的調用封裝在async_to_sync()
包裝器中,因為channel.layers僅提供異步實現,而我們是從同步上下文中調用它。 Django Channels文檔中提供了更多詳細信息。
筆記:
在某些情況下,輪詢仍然是簡單有效的最合適的選擇。
但是,在某些情況下,您可能會遇到一些限制:
使用Websocket,您可以改為(僅當有新數據可用時)通過向客戶端發送特定消息來通知客戶端。
AJAX調用和REST API是您要尋找的組合。 對於實時數據更新,最好的方法是定期輪詢REST API。 就像是:
function doPoll(){
$.post('<api_endpoint_here>', function(data) {
// Do operation to update the data here
setTimeout(doPoll, <how_much_delay>);
});
}
現在,將Django Rest Framework添加到您的項目中。 他們在這里有一個簡單的教程。 創建一個API端點,該端點將以JSON形式返回數據,並在AJAX調用中使用該URL。
現在您可能會感到困惑,因為您是在從home
視圖渲染頁面時將數據作為上下文傳遞到模板中的。 那將不再起作用。 您必須添加腳本來更新元素的值,例如
document.getElementById("element_id").value = "New Value";
其中element_id
是您賦予該元素的ID, "New Value"
是您從AJAX調用的響應中獲取的數據。
我希望這會為您提供一個基本的背景。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.