使用 django 通道在 django 模板中显示 websocket 消息的正确方法是什么?
What's the correct way to get websocket message do display in django template using django channels?
我正在尝试使用渠道和芹菜实时显示来自第三方 api 的股市数据。我正在使用 celery 从 api 和通道获取数据以接收数据并将数据发送到客户端。
我的问题是数据没有在模板中呈现,我的 python 和 javascript 也没有显示任何错误,所以我不知道出了什么问题。帮助将不胜感激。
忽略片段中注释掉的代码。
tasks.py
import requests
from celery import shared_task
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
channel_layer = get_channel_layer()
@shared_task
def get_stock_info ():
# request.session['sym'] = sym
payload = {'symbol': 'nvda'}
# r = requests.get('https://api.twelvedata.com/time_series?&interval=1min&apikey=xxxxxxxxx',
# params=payload)
r = requests.get('https://api.twelvedata.com/price?apikey=xxxxxxxxx',
params=payload)
res = r.json()
price = res['price']
async_to_sync(channel_layer.group_send)('stocks', {'type': 'send_info', 'text': price})
consumers.py
from channels.generic.websocket import AsyncWebsocketConsumer
class StockConsumer(AsyncWebsocketConsumer):
async def connect(self):
await self.channel_layer.group_add('stocks', self.channel_name)
await self.accept()
async def disconnect(self):
await self.channel_layer.group_discard('stocks', self.channel_name)
async def send_info(self, event):
msg = event['text']
await self.send(msg)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p id="#price">{{ text }}</p>
<p id="description">{{ res.Description }}</p>
<script>
var socket = new WebSocket('ws://localhost:8000/ws/stock_info/');
socket.onmessage = function(event){
var price = event.data;
document.querySelector('#price').innerText = price;
}
</script>
</body>
</html>
routing.py
from django.urls import path
from .consumers import StockConsumer
ws_urlpatterns = [
path('ws/stock_info/', StockConsumer.as_asgi())
]
celery.py
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'stockwatch.settings')
app = Celery('stockwatch')
app.config_from_object('django.conf:settings', namespace='CELERY')
# app.conf.beat_schedule = {
# 'get_info_1s': {
# 'task': 'stock_info.tasks.get_stock_info',
# 'schedule': 3.0
# }
# }
app.autodiscover_tasks()
这是我的错误。
<p id="#price">{{ text }}</p>
应该是
<p id="price">{{ text }}</p>
这里的问题出在你的 JS 代码上。当您使用 querySelector
访问价格时。这没有错。当您有一个 id 可以访问时,您就有一个专门的功能,即 getElementById
.
主要错误是,在 HTML 标记中定义一个 id 你不应该使用 #。所以我的建议是这个
像这样做标记
<p id="price">{{ text }}</p>
然后像这样做 JS 部分
document.getElementById('price').innerText = price;
我正在尝试使用渠道和芹菜实时显示来自第三方 api 的股市数据。我正在使用 celery 从 api 和通道获取数据以接收数据并将数据发送到客户端。
我的问题是数据没有在模板中呈现,我的 python 和 javascript 也没有显示任何错误,所以我不知道出了什么问题。帮助将不胜感激。
忽略片段中注释掉的代码。
tasks.py
import requests
from celery import shared_task
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
channel_layer = get_channel_layer()
@shared_task
def get_stock_info ():
# request.session['sym'] = sym
payload = {'symbol': 'nvda'}
# r = requests.get('https://api.twelvedata.com/time_series?&interval=1min&apikey=xxxxxxxxx',
# params=payload)
r = requests.get('https://api.twelvedata.com/price?apikey=xxxxxxxxx',
params=payload)
res = r.json()
price = res['price']
async_to_sync(channel_layer.group_send)('stocks', {'type': 'send_info', 'text': price})
consumers.py
from channels.generic.websocket import AsyncWebsocketConsumer
class StockConsumer(AsyncWebsocketConsumer):
async def connect(self):
await self.channel_layer.group_add('stocks', self.channel_name)
await self.accept()
async def disconnect(self):
await self.channel_layer.group_discard('stocks', self.channel_name)
async def send_info(self, event):
msg = event['text']
await self.send(msg)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p id="#price">{{ text }}</p>
<p id="description">{{ res.Description }}</p>
<script>
var socket = new WebSocket('ws://localhost:8000/ws/stock_info/');
socket.onmessage = function(event){
var price = event.data;
document.querySelector('#price').innerText = price;
}
</script>
</body>
</html>
routing.py
from django.urls import path
from .consumers import StockConsumer
ws_urlpatterns = [
path('ws/stock_info/', StockConsumer.as_asgi())
]
celery.py
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'stockwatch.settings')
app = Celery('stockwatch')
app.config_from_object('django.conf:settings', namespace='CELERY')
# app.conf.beat_schedule = {
# 'get_info_1s': {
# 'task': 'stock_info.tasks.get_stock_info',
# 'schedule': 3.0
# }
# }
app.autodiscover_tasks()
这是我的错误。
<p id="#price">{{ text }}</p>
应该是
<p id="price">{{ text }}</p>
这里的问题出在你的 JS 代码上。当您使用 querySelector
访问价格时。这没有错。当您有一个 id 可以访问时,您就有一个专门的功能,即 getElementById
.
主要错误是,在 HTML 标记中定义一个 id 你不应该使用 #。所以我的建议是这个
像这样做标记
<p id="price">{{ text }}</p>
然后像这样做 JS 部分
document.getElementById('price').innerText = price;