#python #django #django-channels
Вопрос:
Я пытаюсь отображать данные о фондовом рынке из стороннего api в режиме реального времени, используя каналы и сельдерей. Я использую сельдерей для получения данных из 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?amp;interval=1minamp;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()
Комментарии:
1. Пожалуйста, убедитесь, что вы никогда не публикуете свои личные ключи API на общедоступном форуме. Перейдите в Twelvedata и удалите/обновите свои ключи как можно скорее.
2. @Фелипе спасибо, я этого не знал, но это имеет смысл.
Ответ №1:
Это была моя ошибка.
<p id="#price">{{ text }}</p>
Должно быть
<p id="price">{{ text }}</p>
Ответ №2:
Проблема здесь в вашем JS-коде. Когда вы получаете доступ к цене с помощью querySelector
. В этом нет никакой вины. Когда у вас есть идентификатор для доступа, у вас есть специальная функция для него, которая есть getElementById
.
Основная ошибка заключается в том, что в HTML-разметке для определения идентификатора вы не должны использовать #. Поэтому моя рекомендация будет такой
Сделайте разметку вот так
<p id="price">{{ text }}</p>
и сделайте часть JS вот так
document.getElementById('price').innerText = price;