Поправил привязку вч загрузки, сделал модальное окно.

This commit is contained in:
2025-11-12 00:04:55 +03:00
parent 5e94086bf0
commit 902eb23bd8
9 changed files with 526 additions and 60 deletions

View File

@@ -22,31 +22,38 @@ from .utils import get_band_names
class CesiumMapView(LoginRequiredMixin, TemplateView):
"""
Представление для отображения 3D карты с использованием Cesium.
Отображает спутники и их зоны покрытия на интерактивной 3D карте.
"""
template_name = 'mapsapp/map3d.html'
template_name = "mapsapp/map3d.html"
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
context = super().get_context_data(**kwargs)
# Оптимизированный запрос - загружаем только необходимые поля
context['sats'] = Satellite.objects.filter(
parameters__objitems__isnull=False
).distinct().only('id', 'name').order_by('name')
# Фильтруем спутники, у которых есть параметры с привязанными объектами
context["sats"] = (
Satellite.objects.filter(parameters__objitem__isnull=False)
.distinct()
.only("id", "name")
.order_by("name")
)
return context
class GetFootprintsView(LoginRequiredMixin, View):
"""
API для получения зон покрытия (footprints) спутника.
Возвращает список названий зон покрытия для указанного спутника.
"""
def get(self, request, sat_id):
try:
# Оптимизированный запрос - загружаем только поле name
sat_name = Satellite.objects.only('name').get(id=sat_id).name
sat_name = Satellite.objects.only("name").get(id=sat_id).name
footprint_names = get_band_names(sat_name)
return JsonResponse(footprint_names, safe=False)
except Satellite.DoesNotExist:
return JsonResponse({"error": "Спутник не найден"}, status=404)
@@ -57,14 +64,15 @@ class GetFootprintsView(LoginRequiredMixin, View):
class TileProxyView(View):
"""
Прокси для загрузки тайлов карты покрытия спутников.
Кэширует тайлы на 7 дней для улучшения производительности.
"""
# Константы
TILE_BASE_URL = "https://static.satbeams.com/tiles"
CACHE_DURATION = 60 * 60 * 24 * 7 # 7 дней
REQUEST_TIMEOUT = 10 # секунд
@method_decorator(require_GET)
@method_decorator(cache_page(CACHE_DURATION))
def dispatch(self, *args, **kwargs):
@@ -72,7 +80,7 @@ class TileProxyView(View):
def get(self, request, footprint_name, z, x, y):
# Валидация имени footprint
if not footprint_name.replace('-', '').replace('_', '').isalnum():
if not footprint_name.replace("-", "").replace("_", "").isalnum():
return HttpResponse("Invalid footprint name", status=400)
url = f"{self.TILE_BASE_URL}/{footprint_name}/{z}/{x}/{y}.png"
@@ -80,7 +88,7 @@ class TileProxyView(View):
try:
resp = requests.get(url, timeout=self.REQUEST_TIMEOUT)
if resp.status_code == 200:
response = HttpResponse(resp.content, content_type='image/png')
response = HttpResponse(resp.content, content_type="image/png")
response["Access-Control-Allow-Origin"] = "*"
response["Cache-Control"] = f"public, max-age={self.CACHE_DURATION}"
return response
@@ -90,27 +98,38 @@ class TileProxyView(View):
return HttpResponse("Request timeout", status=504)
except requests.RequestException as e:
return HttpResponse(f"Proxy error: {e}", status=500)
class LeafletMapView(LoginRequiredMixin, TemplateView):
"""
Представление для отображения 2D карты с использованием Leaflet.
Отображает спутники и транспондеры на интерактивной 2D карте.
"""
template_name = 'mapsapp/map2d.html'
template_name = "mapsapp/map2d.html"
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
context = super().get_context_data(**kwargs)
# Оптимизированные запросы - загружаем только необходимые поля
context['sats'] = Satellite.objects.filter(
parameters__objitems__isnull=False
).distinct().only('id', 'name').order_by('name')
context['trans'] = Transponders.objects.select_related(
'sat_id', 'polarization'
# Фильтруем спутники, у которых есть параметры с привязанными объектами
context["sats"] = (
Satellite.objects.filter(parameters__objitem__isnull=False)
.distinct()
.only("id", "name")
.order_by("name")
)
context["trans"] = Transponders.objects.select_related(
"sat_id", "polarization"
).only(
'id', 'name', 'sat_id__name', 'polarization__name',
'downlink', 'frequency_range', 'zone_name'
"id",
"name",
"sat_id__name",
"polarization__name",
"downlink",
"frequency_range",
"zone_name",
)
return context
@@ -118,20 +137,22 @@ class LeafletMapView(LoginRequiredMixin, TemplateView):
class GetTransponderOnSatIdView(LoginRequiredMixin, View):
"""
API для получения транспондеров спутника.
Возвращает список транспондеров для указанного спутника с оптимизированными запросами.
"""
def get(self, request, sat_id):
# Оптимизированный запрос с select_related и only
trans = Transponders.objects.filter(
sat_id=sat_id
).select_related('polarization').only(
'name', 'downlink', 'frequency_range',
'zone_name', 'polarization__name'
trans = (
Transponders.objects.filter(sat_id=sat_id)
.select_related("polarization")
.only(
"name", "downlink", "frequency_range", "zone_name", "polarization__name"
)
)
if not trans.exists():
return JsonResponse({'error': 'Объектов не найдено'}, status=404)
return JsonResponse({"error": "Объектов не найдено"}, status=404)
# Используем list comprehension для лучшей производительности
output = [
@@ -140,9 +161,9 @@ class GetTransponderOnSatIdView(LoginRequiredMixin, View):
"frequency": tran.downlink,
"frequency_range": tran.frequency_range,
"zone_name": tran.zone_name,
"polarization": tran.polarization.name if tran.polarization else "-"
"polarization": tran.polarization.name if tran.polarization else "-",
}
for tran in trans
]
return JsonResponse(output, safe=False)
return JsonResponse(output, safe=False)