import datetime from service import serializers from service import models from rest_framework import viewsets from rest_framework.permissions import AllowAny from django.core.serializers import serialize from rest_framework.response import Response import json from django.core.cache import cache from rest_framework import status from rest_framework.decorators import action from django.db.models import Max, Min from django.conf import settings from service.management.commands.create_poly import import_poly from service.management.commands.create_points import import_points from rest_framework.parsers import MultiPartParser import os from django.core.files.storage import default_storage from django.core.files.base import ContentFile from service.utils import get_model_column_names from django.http import HttpResponseRedirect from django.contrib import messages def get_min_max_filters(model, exclude_fields_names): d = {} l = [] fields = get_model_column_names(model, exclude_fields_names) for i in fields: l.append(Min(i)) l.append(Max(i)) qs = model.objects.aggregate(*l) for i in fields: d[i] = [qs[f'{i}__min'], qs[f'{i}__max']] return d def get_full_filters(model, exclude_fields_names): d = {} fields = get_model_column_names(model, exclude_fields_names) values = model.objects.defer('pk').values(*fields) for n, i in enumerate(fields): d[i] = sorted([v[i] for v in values]) return d def get_model_naming(model): return models.Config.objects.get(name=f'{model.__name__}').data class PolygonViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = serializers.PolygonSerializer permission_classes = [AllowAny] parser_classes = (MultiPartParser,) @action(detail=False, methods=['get']) def filters(self, request): d = cache.get('polygon_filters') if settings.DEBUG: d = None if d is None: d = get_full_filters(models.Polygon, ['id', 'geometry']) cache.set('polygon_filters', d, 60 * 60 * 24) return Response(d, status=status.HTTP_200_OK) @action(detail=False, methods=['get']) def naming(self, request): return Response(get_model_naming(models.Polygon), status=status.HTTP_200_OK) @action(detail=False, methods=['post']) def file_import(self, request): try: file = request.FILES['file'].file path = default_storage.save(f'cells/cells_{datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}.zip', ContentFile(file.read())) import_poly(os.path.join(settings.MEDIA_ROOT, path)) cache.delete('polygon_filters') messages.add_message(request, messages.INFO, 'Данные успешно импортированы') except Exception as e: messages.add_message(request, messages.ERROR, f'Ошибка импорта: {e}') return HttpResponseRedirect('/admin/') class PointViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = serializers.PointSerializer permission_classes = [AllowAny] queryset = models.Point.objects.all() def list(self, request, *args, **kwargs): queryset = self.get_queryset() d = cache.get('points') if settings.DEBUG: d = None if d is None: d = json.loads(serialize('geojson', queryset, geometry_field='point', fields=get_model_column_names(models.Point,['point']) )) cache.set('points', d, 60 * 60 * 24) resp = Response(d) resp["Access-Control-Allow-Origin"] = '*' resp["Access-Control-Allow-Methods"] = 'GET,PUT, OPTIONS' resp["Access-Control-Max-Age"] = '1000' resp["Access-Control-Allow-Headers"] = 'X-Requested-With, Content-Type' return resp @action(detail=False, methods=['get']) def filters(self, request): resp = Response(get_min_max_filters(models.Point, ['id', 'point', 'is2025'])) resp["Access-Control-Allow-Origin"] = '*' resp["Access-Control-Allow-Methods"] = 'GET,PUT, OPTIONS' resp["Access-Control-Max-Age"] = '1000' resp["Access-Control-Allow-Headers"] = 'X-Requested-With, Content-Type' return resp @action(detail=False, methods=['post']) def file_import(self, request): try: file = request.FILES['file'].file path = default_storage.save(f'points/points_{datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}.xlsx', ContentFile(file.read())) import_points(os.path.join(settings.MEDIA_ROOT, path)) cache.delete('points') messages.add_message(request, messages.INFO, 'Данные успешно импортированы') except Exception as e: messages.add_message(request, messages.ERROR, f'Ошибка импорта: {e}') return HttpResponseRedirect('/admin/') @action(detail=False, methods=['get']) def naming(self, request): return Response(get_model_naming(models.Point), status=status.HTTP_200_OK)