基于Django的网络设备实时监控:如何实现10秒自动更新状态
Great question! Let's break this down into manageable parts—you'll need a mix of Django backend logic to fetch device statuses, frontend JavaScript for auto-updates, and Mapbox for interactive map visualization. Here's a step-by-step implementation plan:
First, we'll build the foundation to manage your devices and retrieve their statuses via Ping or SNMP.
1.1 Define a Device Model
Create a Django model to store device details (so you don't hardcode them):
from django.db import models class Device(models.Model): MONITOR_TYPES = ( ('ping', 'Ping'), ('snmp', 'SNMP'), ) name = models.CharField(max_length=50) # e.g., PC1 city = models.CharField(max_length=50) # e.g., city1 latitude = models.FloatField() # For Mapbox mapping longitude = models.FloatField() monitor_type = models.CharField(max_length=10, choices=MONITOR_TYPES) target_ip = models.GenericIPAddressField() snmp_community = models.CharField(max_length=50, blank=True, null=True) # Only for SNMP def __str__(self): return f"{self.name} ({self.city})"
1.2 Build Status-Checking Utilities
Write helper functions to ping devices or query SNMP:
# utils.py import subprocess from pysnmp.hlapi import * def check_ping_status(ip): # Cross-platform ping (adjust args for Windows/Linux) ping_args = ['ping', '-c', '2', '-W', '1', ip] if os.name == 'posix' else ['ping', '-n', '2', '-w', '1000', ip] try: result = subprocess.run( ping_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) return result.returncode == 0 # 0 = success except Exception as e: print(f"Ping error for {ip}: {str(e)}") return False def check_snmp_status(ip, community): try: # Query a basic SNMP OID (system description) to confirm reachability errorIndication, errorStatus, _, _ = next( getCmd(SnmpEngine(), CommunityData(community), UdpTransportTarget((ip, 161)), ContextData(), ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0'))) ) return not (errorIndication or errorStatus) except Exception as e: print(f"SNMP error for {ip}: {str(e)}") return False
1.3 Create an API Endpoint for Status Data
Build a Django view that returns device statuses as JSON (for frontend consumption):
# views.py from django.http import JsonResponse from .models import Device from .utils import check_ping_status, check_snmp_status def device_status_api(request): devices = Device.objects.all() status_list = [] for device in devices: is_online = False if device.monitor_type == 'ping': is_online = check_ping_status(device.target_ip) else: is_online = check_snmp_status(device.target_ip, device.snmp_community) status_list.append({ 'id': device.id, 'name': device.name, 'city': device.city, 'lat': device.latitude, 'lon': device.longitude, 'is_online': is_online }) return JsonResponse({'devices': status_list})
Don't forget to map this view in your urls.py:
path('api/device-status/', views.device_status_api, name='device-status-api')
Now we'll build the webpage that pulls status data every 10 seconds and displays it on a Mapbox map.
2.1 Mapbox Integration & Auto-Update Logic
Add this to your Django template (replace YOUR_MAPBOX_TOKEN with your actual token from Mapbox):
<!-- map_template.html --> <!DOCTYPE html> <html> <head> <title>Device Status Monitor</title> <script src='https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.js'></script> <link href='https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.css' rel='stylesheet' /> <style> #map { width: 100%; height: 70vh; } .status-badge { padding: 8px; margin: 10px 0; border-radius: 4px; } .online { background-color: #d4edda; color: #155724; } .offline { background-color: #f8d7da; color: #721c24; } </style> </head> <body> <h1>Distributed Device Monitor</h1> <div id="status-summary" class="status-badge"></div> <div id="map"></div> <script> mapboxgl.accessToken = 'YOUR_MAPBOX_TOKEN'; const map = new mapboxgl.Map({ container: 'map', style: 'mapbox://styles/mapbox/streets-v12', center: [0, 0], // Adjust to your devices' average location zoom: 2 }); // Store markers to update them later (avoid re-creating every time) const deviceMarkers = {}; // Fetch and update statuses function updateStatuses() { fetch('/api/device-status/') .then(res => res.json()) .then(data => { const summaryDiv = document.getElementById('status-summary'); const onlineCount = data.devices.filter(d => d.is_online).length; summaryDiv.textContent = `Last updated: ${new Date().toLocaleString()} | ${onlineCount}/${data.devices.length} devices online`; summaryDiv.className = `status-badge ${onlineCount === data.devices.length ? 'online' : 'offline'}`; // Update map markers data.devices.forEach(device => { const markerColor = device.is_online ? '#2ecc71' : '#e74c3c'; if (deviceMarkers[device.id]) { // Update existing marker color deviceMarkers[device.id].getElement().style.backgroundColor = markerColor; deviceMarkers[device.id].getElement().title = `${device.name} (${device.city}): ${device.is_online ? 'Online' : 'Offline'}`; } else { // Create new marker const markerEl = document.createElement('div'); markerEl.style.width = '22px'; markerEl.style.height = '22px'; markerEl.style.borderRadius = '50%'; markerEl.style.backgroundColor = markerColor; markerEl.style.cursor = 'pointer'; markerEl.title = `${device.name} (${device.city}): ${device.is_online ? 'Online' : 'Offline'}`; const marker = new mapboxgl.Marker(markerEl) .setLngLat([device.lon, device.lat]) .addTo(map); deviceMarkers[device.id] = marker; } }); }) .catch(err => { console.error('Failed to fetch status:', err); document.getElementById('status-summary').textContent = 'Error updating status - retrying...'; document.getElementById('status-summary').className = 'status-badge offline'; }); } // Initial load + auto-update every 10 seconds window.onload = () => { updateStatuses(); setInterval(updateStatuses, 10000); }; </script> </body> </html>
- Performance: For large numbers of devices, use Celery + Redis to pre-fetch statuses asynchronously (e.g., every 5 seconds) and cache results. The API can then return cached data instead of running checks on every request.
- Error Handling: Add retries for failed ping/SNMP checks, and handle cases where devices are unreachable (don't just return
False—log the error for debugging). - Security: Never expose SNMP community strings in frontend code. All SNMP/Ping logic runs exclusively on the backend. Add Django authentication to the API endpoint if needed.
- Cross-Platform Compatibility: The ping utility uses different arguments on Windows vs. Linux—we added a check for
os.nameto handle this, but test it in your environment.
内容的提问来源于stack exchange,提问作者shami shami

