Files
aerbim-ht-monitor/backend/api/account/views/dashboard_views.py

109 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from drf_spectacular.utils import extend_schema, OpenApiResponse, OpenApiExample, OpenApiParameter
from api.utils.decorators import handle_exceptions
from datetime import timedelta
from django.utils import timezone
from django.db.models import Count
from django.db.models.functions import TruncHour
from sitemanagement.models import Alert
from api.account.serializers.dashboard_serializers import DashboardSerializer
@extend_schema(tags=['Дашборд'])
class DashboardView(APIView):
permission_classes = [IsAuthenticated]
@extend_schema(
summary="Получение статистики алертов",
description="Возвращает статистику алертов за выбранный период времени",
parameters=[OpenApiParameter(
name='time_period',
type=str,
location=OpenApiParameter.QUERY,
description='Период времени в часах',
required=False,
enum=['24', '72', '168', '720'],
default='168'
)],
responses = {
200: OpenApiResponse(response=DashboardSerializer, description="Данные для дашборда успешно получены",
examples=[OpenApiExample(
'Успешный ответ',
value={
"chart_data": [
{"timestamp": "2025-10-07T10:00:00+03:00", "value": 5},
{"timestamp": "2025-10-07T11:00:00+03:00", "value": 3}
],
"table_data": [
{
"id": 1,
"name": "GA-1",
"object": "Объект 1",
"metric_value": "23.5 °C",
"sensor_type_name": "Датчик температуры",
"message": "Превышение температуры",
"severity": "warning",
"created_at": "2025-10-07T10:30:00+03:00",
"resolved": False
}
]
}
)])
}
)
@handle_exceptions
def get(self, request):
time_period = request.query_params.get('time_period', '168')
if time_period not in ['720', '168', '72', '24']:
return Response(
- {"error": "Неверный период. Допустимые значения: 720, 168, 72, 24"},
+ {"error": "Неверный период. Допустимые значения: 24, 72, 168, 720"},
status=status.HTTP_400_BAD_REQUEST
)
# определяем начальную дату
start_date = timezone.now() - timedelta(hours=int(time_period))
# получаем все алерты за период с фронта
alerts = Alert.objects.filter(created_at__gte=start_date)
# данные для графиков (группировка по часам)
alerts_by_hour = alerts.annotate(
hour=TruncHour('created_at')
).values('hour').annotate(
count=Count('id')
).order_by('hour')
# !! обязательно локальное время
chart_data = []
for entry in alerts_by_hour:
local_time = timezone.localtime(entry['hour'])
chart_data.append({
"timestamp": local_time.isoformat(),
"value": entry['count']
})
# данные для таблицы с алертами
alerts_list = alerts.select_related(
'sensor',
'sensor_type',
'metric',
'sensor__signal_format'
).prefetch_related(
'sensor__zones',
'sensor__zones__object'
).order_by('-created_at')
dashboard_data = {
"chart_data": chart_data,
"table_data": alerts_list
}
serializer = DashboardSerializer(instance=dashboard_data)
return Response(serializer.data, status=status.HTTP_200_OK)