Добавил геофильтры. Теперь нужен рефакторинг.

This commit is contained in:
2025-11-17 17:44:24 +03:00
parent b889fb29a3
commit c0f2f16303
7 changed files with 385 additions and 2 deletions

View File

@@ -1,10 +1,12 @@
"""
Source related views.
"""
import json
from datetime import datetime
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.gis.geos import Point, Polygon as GEOSPolygon
from django.core.paginator import Paginator
from django.db.models import Count, Q
from django.http import JsonResponse
@@ -62,6 +64,23 @@ class SourceListView(LoginRequiredMixin, View):
snr_min = request.GET.get("snr_min", "").strip()
snr_max = request.GET.get("snr_max", "").strip()
# Get polygon filter
polygon_coords_str = request.GET.get("polygon", "").strip()
polygon_coords = None
polygon_geom = None
if polygon_coords_str:
try:
polygon_coords = json.loads(polygon_coords_str)
if polygon_coords and len(polygon_coords) >= 4:
# Create GEOS Polygon from coordinates
# Coordinates are in [lng, lat] format
polygon_geom = GEOSPolygon(polygon_coords, srid=4326)
except (json.JSONDecodeError, ValueError, TypeError) as e:
# Invalid polygon data, ignore
polygon_coords = None
polygon_geom = None
# Get all satellites for filter
satellites = (
Satellite.objects.filter(parameters__objitem__source__isnull=False)
@@ -210,6 +229,11 @@ class SourceListView(LoginRequiredMixin, View):
objitem_filter_q &= Q(source_objitems__geo_obj__mirrors__id__in=selected_mirrors)
has_objitem_filter = True
# Add polygon filter
if polygon_geom:
objitem_filter_q &= Q(source_objitems__geo_obj__coords__within=polygon_geom)
has_objitem_filter = True
# Get all Source objects with query optimization
# Using annotate to count ObjItems efficiently (single query with GROUP BY)
# Using prefetch_related for reverse ForeignKey relationships to avoid N+1 queries
@@ -443,6 +467,12 @@ class SourceListView(LoginRequiredMixin, View):
source_objitems__geo_obj__mirrors__id__in=selected_mirrors
).distinct()
# Filter by polygon
if polygon_geom:
sources = sources.filter(
source_objitems__geo_obj__coords__within=polygon_geom
).distinct()
# Apply sorting
valid_sort_fields = {
"id": "id",
@@ -540,6 +570,8 @@ class SourceListView(LoginRequiredMixin, View):
objitems_to_display = objitems_to_display.filter(geo_obj__mirrors__id__in=selected_mirrors)
if search_by_name:
objitems_to_display = objitems_to_display.filter(name__icontains=search_query)
if polygon_geom:
objitems_to_display = objitems_to_display.filter(geo_obj__coords__within=polygon_geom)
# Use annotated count (consistent with filtering)
objitem_count = source.objitem_count
@@ -652,6 +684,7 @@ class SourceListView(LoginRequiredMixin, View):
int(x) if isinstance(x, str) else x for x in selected_mirrors if (isinstance(x, int) or (isinstance(x, str) and x.isdigit()))
],
'object_infos': object_infos,
'polygon_coords': json.dumps(polygon_coords) if polygon_coords else None,
'full_width_page': True,
}