feat: 优化的mplogxview
This commit is contained in:
parent
1689683aa3
commit
820f814766
|
@ -1,18 +1,19 @@
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from rest_framework.routers import DefaultRouter
|
from rest_framework.routers import DefaultRouter
|
||||||
from apps.enm.views import (MpointViewSet, MpLogxViewSet, MpointStatViewSet,
|
from apps.enm.views import (MpointViewSet, MpointStatViewSet,
|
||||||
EnStatViewSet, EnStat2ViewSet, XscriptViewSet)
|
EnStatViewSet, EnStat2ViewSet, XscriptViewSet, MpLogxAPIView)
|
||||||
|
|
||||||
API_BASE_URL = 'api/enm/'
|
API_BASE_URL = 'api/enm/'
|
||||||
HTML_BASE_URL = 'dhtml/enm/'
|
HTML_BASE_URL = 'dhtml/enm/'
|
||||||
|
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
router.register('mpoint', MpointViewSet, basename='mpoint')
|
router.register('mpoint', MpointViewSet, basename='mpoint')
|
||||||
router.register('mplogx', MpLogxViewSet, basename='mplogx')
|
# router.register('mplogx', MpLogxViewSet, basename='mplogx')
|
||||||
router.register('mpointstat', MpointStatViewSet, basename='mpointstat')
|
router.register('mpointstat', MpointStatViewSet, basename='mpointstat')
|
||||||
router.register('enstat', EnStatViewSet, basename='enstat')
|
router.register('enstat', EnStatViewSet, basename='enstat')
|
||||||
router.register('enstat2', EnStat2ViewSet, basename='enstat2')
|
router.register('enstat2', EnStat2ViewSet, basename='enstat2')
|
||||||
router.register('xscript', XscriptViewSet, basename='xscript')
|
router.register('xscript', XscriptViewSet, basename='xscript')
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path(API_BASE_URL, include(router.urls)),
|
path(API_BASE_URL, include(router.urls)),
|
||||||
|
path(f'{API_BASE_URL}mplogx/', MpLogxAPIView.as_view(), name='mplogx_list'),
|
||||||
]
|
]
|
|
@ -12,6 +12,7 @@ from apps.enm.tasks import cal_mpointstat_manual
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.serializers import Serializer
|
from rest_framework.serializers import Serializer
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
|
from rest_framework.views import APIView
|
||||||
from apps.enm.tasks import cal_mpointstats_duration
|
from apps.enm.tasks import cal_mpointstats_duration
|
||||||
from apps.enm.services import king_sync, MpointCache
|
from apps.enm.services import king_sync, MpointCache
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
@ -21,7 +22,13 @@ from apps.enm.services import get_analyse_data_mgroups_duration
|
||||||
from django.db.models import Sum
|
from django.db.models import Sum
|
||||||
import logging
|
import logging
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
from apps.utils.sql import query_one_dict, query_all_dict
|
||||||
|
from drf_yasg import openapi
|
||||||
|
from drf_yasg.utils import swagger_auto_schema
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
myLogger = logging.getLogger('log')
|
myLogger = logging.getLogger('log')
|
||||||
|
|
||||||
class MpointViewSet(CustomModelViewSet):
|
class MpointViewSet(CustomModelViewSet):
|
||||||
"""
|
"""
|
||||||
list:测点
|
list:测点
|
||||||
|
@ -166,6 +173,97 @@ class XscriptViewSet(CustomModelViewSet):
|
||||||
# select_related_fields = ['mpoint']
|
# select_related_fields = ['mpoint']
|
||||||
# filterset_fields = ['mpoint', 'mpoint__mgroup', 'mpoint__mgroup__belong_dept']
|
# filterset_fields = ['mpoint', 'mpoint__mgroup', 'mpoint__mgroup__belong_dept']
|
||||||
|
|
||||||
|
class MpLogxAPIView(APIView):
|
||||||
|
"""
|
||||||
|
list:测点采集数据
|
||||||
|
|
||||||
|
测点采集数据
|
||||||
|
"""
|
||||||
|
perms_map = {"get": "*"}
|
||||||
|
|
||||||
|
@swagger_auto_schema(manual_parameters=[
|
||||||
|
openapi.Parameter('mpoint', openapi.IN_QUERY, description='测点ID', type=openapi.TYPE_STRING),
|
||||||
|
openapi.Parameter('timex__gte', openapi.IN_QUERY, description='开始时间', type=openapi.TYPE_STRING),
|
||||||
|
openapi.Parameter('timex__lte', openapi.IN_QUERY, description='结束时间', type=openapi.TYPE_STRING),
|
||||||
|
openapi.Parameter('page', openapi.IN_QUERY, description='页码', type=openapi.TYPE_INTEGER),
|
||||||
|
openapi.Parameter('page_size', openapi.IN_QUERY, description='每页数量', type=openapi.TYPE_INTEGER),
|
||||||
|
openapi.Parameter('ordering', openapi.IN_QUERY, description='排序字段,如 -timex', type=openapi.TYPE_STRING),
|
||||||
|
openapi.Parameter('fields', openapi.IN_QUERY, description='返回字段,如 timex,val_float,val_int', type=openapi.TYPE_STRING),
|
||||||
|
])
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
mpoint = request.query_params.get("mpoint", None)
|
||||||
|
timex__gte_str = request.query_params.get("timex__gte", None)
|
||||||
|
timex__lte_str = request.query_params.get("timex__lte", None)
|
||||||
|
page = int(request.query_params.get("page", 1))
|
||||||
|
page_size = int(request.query_params.get("page_size", 20))
|
||||||
|
fields = request.query_params.get("fields", None)
|
||||||
|
if page < 0 and page_size < 0:
|
||||||
|
raise ParseError("page, page_size must be positive")
|
||||||
|
ordering = request.query_params.get("ordering", "-timex") # 默认倒序
|
||||||
|
|
||||||
|
if mpoint is None or timex__gte_str is None:
|
||||||
|
raise ParseError("mpoint, timex__gte are required")
|
||||||
|
|
||||||
|
# 处理时间
|
||||||
|
timex__gte = timezone.make_aware(datetime.strptime(timex__gte_str, "%Y-%m-%d %H:%M:%S"))
|
||||||
|
timex__lte = timezone.make_aware(datetime.strptime(timex__lte_str, "%Y-%m-%d %H:%M:%S")) if timex__lte_str else timezone.now()
|
||||||
|
|
||||||
|
# 统计总数
|
||||||
|
count_sql = """SELECT COUNT(*) AS total_count FROM enm_mplogx
|
||||||
|
WHERE mpoint_id=%s AND timex >= %s AND timex <= %s"""
|
||||||
|
count_data = query_one_dict(count_sql, [mpoint, timex__gte, timex__lte], with_time_format=True)
|
||||||
|
|
||||||
|
# 排序白名单
|
||||||
|
allowed_fields = {"timex", "val_mrs", "val_int", "val_float"} # 根据表字段修改
|
||||||
|
order_fields = []
|
||||||
|
for field in ordering.split(","):
|
||||||
|
field = field.strip()
|
||||||
|
if not field:
|
||||||
|
continue
|
||||||
|
desc = field.startswith("-")
|
||||||
|
field_name = field[1:] if desc else field
|
||||||
|
if field_name in allowed_fields:
|
||||||
|
order_fields.append(f"{field_name} {'DESC' if desc else 'ASC'}")
|
||||||
|
|
||||||
|
# 如果没有合法字段,使用默认排序
|
||||||
|
if not order_fields:
|
||||||
|
order_fields = ["timex DESC"]
|
||||||
|
|
||||||
|
order_clause = "ORDER BY " + ", ".join(order_fields)
|
||||||
|
|
||||||
|
# 构造 SQL
|
||||||
|
if page == 0:
|
||||||
|
if fields:
|
||||||
|
# 过滤白名单,避免非法列
|
||||||
|
fields = [f for f in fields.split(",") if f in allowed_fields]
|
||||||
|
if not fields:
|
||||||
|
fields = ["timex", "val_float", "val_int"] # 默认列
|
||||||
|
select_clause = ", ".join(fields)
|
||||||
|
else:
|
||||||
|
select_clause = "timex, val_float, val_int" # 默认列
|
||||||
|
page_sql = f"""SELECT {select_clause} FROM enm_mplogx
|
||||||
|
WHERE mpoint_id=%s AND timex >= %s AND timex <= %s
|
||||||
|
{order_clause}"""
|
||||||
|
page_params = [mpoint, timex__gte, timex__lte]
|
||||||
|
else:
|
||||||
|
page_sql = f"""SELECT * FROM enm_mplogx
|
||||||
|
WHERE mpoint_id=%s AND timex >= %s AND timex <= %s
|
||||||
|
{order_clause} LIMIT %s OFFSET %s"""
|
||||||
|
page_params = [mpoint, timex__gte, timex__lte, page_size, (page-1)*page_size]
|
||||||
|
|
||||||
|
page_data = query_all_dict(page_sql, page_params, with_time_format=True)
|
||||||
|
|
||||||
|
if page == 0:
|
||||||
|
return Response(page_data)
|
||||||
|
|
||||||
|
return Response({
|
||||||
|
"count": count_data["total_count"],
|
||||||
|
"page": page,
|
||||||
|
"page_size": page_size,
|
||||||
|
"results": page_data
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MpLogxViewSet(CustomListModelMixin, CustomGenericViewSet):
|
class MpLogxViewSet(CustomListModelMixin, CustomGenericViewSet):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue