如何在Django中实时显示Arduino投币数据且无需刷新页面?
Django实时显示Arduino投币数据的解决方案
方法一:前端定时轮询(简单易实现)
通过前端定时请求后端接口获取最新数据,无需刷新页面即可更新内容,适合新手快速上手。
1. 新增后端API接口
修改views.py,添加仅返回数据的视图:
from django.http import JsonResponse import serial def get_coin_data(request): try: arduino = serial.Serial('COM6', 9600) data = arduino.readline().decode().strip() arduino.close() return JsonResponse({'data': data}) except Exception as e: return JsonResponse({'data': f"Error communicating with Arduino: {str(e)}"}, status=500)
在项目urls.py中添加路由:
from django.urls import path from . import views urlpatterns = [ # 保留原有路由 path('get-coin-data/', views.get_coin_data, name='get_coin_data'), ]
2. 前端添加定时更新逻辑
修改usb.html,加入JavaScript定时请求并更新页面:
<div class="estimated-price"> <label>Inserted Coins:</label> <span id="inserted-coins">₱{{data}}</span> </div> <script> function updateCoinData() { fetch('/get-coin-data/') .then(response => response.json()) .then(result => { document.getElementById('inserted-coins').textContent = '₱' + result.data; }) .catch(err => console.error('获取数据失败:', err)); } // 页面加载后立即更新,之后每隔1秒刷新一次 updateCoinData(); setInterval(updateCoinData, 1000); </script>
注意:此方式每次请求都会开关串口,频繁操作可能不稳定,后续可优化为后端保持串口长连接。
方法二:WebSockets实时推送(高效稳定)
通过Django Channels实现WebSockets,后端主动推送Arduino数据到前端,适合持续数据传输场景。
1. 安装并配置Django Channels
安装依赖:
pip install channels
修改settings.py:
INSTALLED_APPS = [ # 保留原有应用 'channels', ] ASGI_APPLICATION = '你的项目名称.asgi.application'
2. 创建WebSockets消费者
在应用目录下新建consumers.py:
import asyncio import serial from channels.generic.websocket import AsyncWebsocketConsumer class CoinConsumer(AsyncWebsocketConsumer): async def connect(self): await self.accept() asyncio.create_task(self.read_arduino_stream()) async def read_arduino_stream(self): try: arduino = serial.Serial('COM6', 9600) while True: data = arduino.readline().decode().strip() await self.send(text_data=data) await asyncio.sleep(0.1) except Exception as e: await self.send(text_data=f"Error communicating with Arduino: {str(e)}") arduino.close() async def disconnect(self, close_code): if hasattr(self, 'arduino'): self.arduino.close()
3. 配置WebSockets路由
项目根目录新建routing.py:
from django.urls import re_path from .consumers import CoinConsumer websocket_urlpatterns = [ re_path(r'ws/coin-data/$', CoinConsumer.as_asgi()), ]
修改asgi.py:
import os from django.core.asgi import get_asgi_application from channels.routing import ProtocolTypeRouter, URLRouter from . import routing os.environ.setdefault('DJANGO_SETTINGS_MODULE', '你的项目名称.settings') application = ProtocolTypeRouter({ "http": get_asgi_application(), "websocket": URLRouter(routing.websocket_urlpatterns), })
4. 前端连接WebSockets
修改usb.html:
<div class="estimated-price"> <label>Inserted Coins:</label> <span id="inserted-coins">₱{{data}}</span> </div> <script> const socket = new WebSocket('ws://' + window.location.host + '/ws/coin-data/'); socket.onmessage = function(e) { document.getElementById('inserted-coins').textContent = '₱' + e.data; }; socket.onclose = function(e) { console.error('WebSocket连接断开,3秒后重试'); setTimeout(() => window.location.reload(), 3000); }; </script>
通用注意事项
- 串口权限:确保运行Django的用户拥有串口访问权限(Linux/Mac需将用户加入dialout组)。
- 稳定性优化:轮询模式可改为后端保持串口长连接,避免频繁开关;WebSockets模式需处理重连逻辑。
- 错误提示:可在前端添加错误状态的友好展示,提升用户体验。
内容的提问来源于stack exchange,提问作者Pyxxelated
相关产品推荐
相关产品推荐

