Страница с Кубсатами
This commit is contained in:
@@ -49,6 +49,10 @@ from .map import (
|
||||
ShowSourceAveragingStepsMapView,
|
||||
ClusterTestView,
|
||||
)
|
||||
from .kubsat import (
|
||||
KubsatView,
|
||||
KubsatExportView,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
# Base
|
||||
@@ -102,4 +106,7 @@ __all__ = [
|
||||
'ShowSourceWithPointsMapView',
|
||||
'ShowSourceAveragingStepsMapView',
|
||||
'ClusterTestView',
|
||||
# Kubsat
|
||||
'KubsatView',
|
||||
'KubsatExportView',
|
||||
]
|
||||
|
||||
330
dbapp/mainapp/views/kubsat.py
Normal file
330
dbapp/mainapp/views/kubsat.py
Normal file
@@ -0,0 +1,330 @@
|
||||
"""
|
||||
Представления для страницы Кубсат с фильтрацией и экспортом в Excel
|
||||
"""
|
||||
from datetime import datetime
|
||||
from io import BytesIO
|
||||
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.gis.geos import Point
|
||||
from django.db.models import Count, Q
|
||||
from django.http import HttpResponse
|
||||
from django.views.generic import FormView
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.styles import Font, Alignment
|
||||
|
||||
from mainapp.forms import KubsatFilterForm
|
||||
from mainapp.models import Source, ObjItem
|
||||
from mainapp.utils import calculate_mean_coords
|
||||
|
||||
|
||||
class KubsatView(LoginRequiredMixin, FormView):
|
||||
"""Страница Кубсат с фильтрами и таблицей источников"""
|
||||
template_name = 'mainapp/kubsat.html'
|
||||
form_class = KubsatFilterForm
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['full_width_page'] = True
|
||||
|
||||
# Если форма была отправлена, применяем фильтры
|
||||
if self.request.GET:
|
||||
form = self.form_class(self.request.GET)
|
||||
if form.is_valid():
|
||||
sources = self.apply_filters(form.cleaned_data)
|
||||
|
||||
# Определяем, какие источники подходят по дате
|
||||
date_from = form.cleaned_data.get('date_from')
|
||||
date_to = form.cleaned_data.get('date_to')
|
||||
|
||||
# Добавляем информацию о соответствии дате для каждого источника
|
||||
sources_with_date_info = []
|
||||
for source in sources:
|
||||
source_data = {
|
||||
'source': source,
|
||||
'matches_date': False,
|
||||
'objitems_data': []
|
||||
}
|
||||
|
||||
# Проверяем каждый ObjItem
|
||||
for objitem in source.source_objitems.all():
|
||||
objitem_matches_date = False
|
||||
geo_date = None
|
||||
|
||||
if hasattr(objitem, 'geo_obj') and objitem.geo_obj and objitem.geo_obj.timestamp:
|
||||
geo_date = objitem.geo_obj.timestamp.date()
|
||||
|
||||
# Проверяем попадание в диапазон дат
|
||||
if date_from and date_to:
|
||||
objitem_matches_date = date_from <= geo_date <= date_to
|
||||
elif date_from:
|
||||
objitem_matches_date = geo_date >= date_from
|
||||
elif date_to:
|
||||
objitem_matches_date = geo_date <= date_to
|
||||
else:
|
||||
objitem_matches_date = True # Нет фильтра по дате
|
||||
|
||||
source_data['objitems_data'].append({
|
||||
'objitem': objitem,
|
||||
'matches_date': objitem_matches_date,
|
||||
'geo_date': geo_date
|
||||
})
|
||||
|
||||
# Если хотя бы одна точка подходит по дате, весь источник подходит
|
||||
if objitem_matches_date:
|
||||
source_data['matches_date'] = True
|
||||
|
||||
sources_with_date_info.append(source_data)
|
||||
|
||||
context['sources_with_date_info'] = sources_with_date_info
|
||||
context['form'] = form
|
||||
|
||||
return context
|
||||
|
||||
def apply_filters(self, filters):
|
||||
"""Применяет фильтры к queryset Source"""
|
||||
queryset = Source.objects.select_related('info').prefetch_related(
|
||||
'source_objitems__parameter_obj__id_satellite',
|
||||
'source_objitems__parameter_obj__polarization',
|
||||
'source_objitems__parameter_obj__modulation',
|
||||
'source_objitems__transponder__sat_id'
|
||||
).annotate(objitem_count=Count('source_objitems'))
|
||||
|
||||
# Фильтр по спутникам
|
||||
if filters.get('satellites'):
|
||||
queryset = queryset.filter(
|
||||
source_objitems__parameter_obj__id_satellite__in=filters['satellites']
|
||||
).distinct()
|
||||
|
||||
# Фильтр по полосе спутника (пока не реализован полностью)
|
||||
if filters.get('band'):
|
||||
pass # TODO: реализовать фильтр по band
|
||||
|
||||
# Фильтр по поляризации
|
||||
if filters.get('polarization'):
|
||||
queryset = queryset.filter(
|
||||
source_objitems__parameter_obj__polarization__in=filters['polarization']
|
||||
).distinct()
|
||||
|
||||
# Фильтр по центральной частоте
|
||||
if filters.get('frequency_min'):
|
||||
queryset = queryset.filter(
|
||||
source_objitems__parameter_obj__frequency__gte=filters['frequency_min']
|
||||
)
|
||||
if filters.get('frequency_max'):
|
||||
queryset = queryset.filter(
|
||||
source_objitems__parameter_obj__frequency__lte=filters['frequency_max']
|
||||
)
|
||||
|
||||
# Фильтр по полосе частот
|
||||
if filters.get('freq_range_min'):
|
||||
queryset = queryset.filter(
|
||||
source_objitems__parameter_obj__freq_range__gte=filters['freq_range_min']
|
||||
)
|
||||
if filters.get('freq_range_max'):
|
||||
queryset = queryset.filter(
|
||||
source_objitems__parameter_obj__freq_range__lte=filters['freq_range_max']
|
||||
)
|
||||
|
||||
# Фильтр по модуляции
|
||||
if filters.get('modulation'):
|
||||
queryset = queryset.filter(
|
||||
source_objitems__parameter_obj__modulation__in=filters['modulation']
|
||||
).distinct()
|
||||
|
||||
# Фильтр по типу объекта
|
||||
if filters.get('object_type'):
|
||||
queryset = queryset.filter(info__in=filters['object_type'])
|
||||
|
||||
# Фильтр по количеству ObjItem
|
||||
objitem_count = filters.get('objitem_count')
|
||||
if objitem_count == '1':
|
||||
queryset = queryset.filter(objitem_count=1)
|
||||
elif objitem_count == '2+':
|
||||
queryset = queryset.filter(objitem_count__gte=2)
|
||||
|
||||
# Фиктивные фильтры (пока не применяются)
|
||||
# has_plans, success_1, success_2, date_from, date_to
|
||||
|
||||
return queryset.distinct()
|
||||
|
||||
|
||||
class KubsatExportView(LoginRequiredMixin, FormView):
|
||||
"""Экспорт отфильтрованных данных в Excel"""
|
||||
form_class = KubsatFilterForm
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
# Получаем список ID точек (ObjItem) из POST
|
||||
objitem_ids = request.POST.getlist('objitem_ids')
|
||||
|
||||
if not objitem_ids:
|
||||
return HttpResponse("Нет данных для экспорта", status=400)
|
||||
|
||||
# Получаем ObjItem с их источниками
|
||||
objitems = ObjItem.objects.filter(id__in=objitem_ids).select_related(
|
||||
'source',
|
||||
'source__info',
|
||||
'parameter_obj__id_satellite',
|
||||
'parameter_obj__polarization',
|
||||
'transponder__sat_id',
|
||||
'geo_obj'
|
||||
).prefetch_related('geo_obj__mirrors')
|
||||
|
||||
# Группируем ObjItem по Source для расчета инкрементального среднего
|
||||
sources_objitems = {}
|
||||
for objitem in objitems:
|
||||
if objitem.source:
|
||||
if objitem.source.id not in sources_objitems:
|
||||
sources_objitems[objitem.source.id] = {
|
||||
'source': objitem.source,
|
||||
'objitems': []
|
||||
}
|
||||
sources_objitems[objitem.source.id]['objitems'].append(objitem)
|
||||
|
||||
# Создаем Excel файл
|
||||
wb = Workbook()
|
||||
ws = wb.active
|
||||
ws.title = "Кубсат"
|
||||
|
||||
# Заголовки
|
||||
headers = [
|
||||
'Дата',
|
||||
'Широта, град',
|
||||
'Долгота, град',
|
||||
'Высота, м',
|
||||
'Местоположение',
|
||||
'ИСЗ',
|
||||
'Прямой канал, МГц',
|
||||
'Обратный канал, МГц',
|
||||
'Перенос',
|
||||
'Получено координат, раз',
|
||||
'Дата',
|
||||
'Зеркала',
|
||||
'СКО, км',
|
||||
'Примечание',
|
||||
'Оператор'
|
||||
]
|
||||
|
||||
# Стиль заголовков
|
||||
for col_num, header in enumerate(headers, 1):
|
||||
cell = ws.cell(row=1, column=col_num, value=header)
|
||||
cell.font = Font(bold=True)
|
||||
cell.alignment = Alignment(horizontal='center', vertical='center')
|
||||
|
||||
# Заполняем данные
|
||||
current_date = datetime.now().strftime('%d.%m.%Y')
|
||||
operator_name = f"{request.user.first_name} {request.user.last_name}" if request.user.first_name else request.user.username
|
||||
|
||||
row_num = 2
|
||||
for source_id, data in sources_objitems.items():
|
||||
source = data['source']
|
||||
objitems_list = data['objitems']
|
||||
|
||||
# Рассчитываем инкрементальное среднее координат из оставшихся точек
|
||||
average_coords = None
|
||||
for objitem in objitems_list:
|
||||
if hasattr(objitem, 'geo_obj') and objitem.geo_obj and objitem.geo_obj.coords:
|
||||
coord = (objitem.geo_obj.coords.x, objitem.geo_obj.coords.y)
|
||||
|
||||
if average_coords is None:
|
||||
# Первая точка
|
||||
average_coords = coord
|
||||
else:
|
||||
# Инкрементальное усреднение
|
||||
average_coords, _ = calculate_mean_coords(average_coords, coord)
|
||||
|
||||
# Если нет координат из geo_obj, берем из source
|
||||
if average_coords is None:
|
||||
coords = source.coords_kupsat or source.coords_average or source.coords_valid or source.coords_reference
|
||||
if coords:
|
||||
average_coords = (coords.x, coords.y)
|
||||
|
||||
latitude = average_coords[1] if average_coords else ''
|
||||
longitude = average_coords[0] if average_coords else ''
|
||||
|
||||
# Получаем местоположение из первого ObjItem с geo_obj
|
||||
location = ''
|
||||
for objitem in objitems_list:
|
||||
if hasattr(objitem, 'geo_obj') and objitem.geo_obj and objitem.geo_obj.location:
|
||||
location = objitem.geo_obj.location
|
||||
break
|
||||
|
||||
# Получаем данные спутника и частоты
|
||||
satellite_info = ''
|
||||
reverse_channel = ''
|
||||
direct_channel = ''
|
||||
transfer = ''
|
||||
|
||||
for objitem in objitems_list:
|
||||
if hasattr(objitem, 'parameter_obj') and objitem.parameter_obj:
|
||||
param = objitem.parameter_obj
|
||||
if param.id_satellite:
|
||||
sat_name = param.id_satellite.name
|
||||
norad = f"({param.id_satellite.norad})" if param.id_satellite.norad else ""
|
||||
satellite_info = f"{sat_name} {norad}"
|
||||
|
||||
if param.frequency:
|
||||
reverse_channel = param.frequency
|
||||
|
||||
if objitem.transponder and objitem.transponder.transfer:
|
||||
transfer = objitem.transponder.transfer
|
||||
if param.frequency:
|
||||
direct_channel = param.frequency + objitem.transponder.transfer
|
||||
|
||||
break
|
||||
|
||||
objitem_count = len(objitems_list)
|
||||
|
||||
# Зеркала
|
||||
mirrors = []
|
||||
for objitem in objitems_list:
|
||||
if hasattr(objitem, 'geo_obj') and objitem.geo_obj:
|
||||
for mirror in objitem.geo_obj.mirrors.all():
|
||||
if mirror.name not in mirrors:
|
||||
mirrors.append(mirror.name)
|
||||
mirrors_str = '\n'.join(mirrors)
|
||||
|
||||
# Записываем строку
|
||||
ws.cell(row=row_num, column=1, value=current_date)
|
||||
ws.cell(row=row_num, column=2, value=latitude)
|
||||
ws.cell(row=row_num, column=3, value=longitude)
|
||||
ws.cell(row=row_num, column=4, value=0) # Высота всегда 0
|
||||
ws.cell(row=row_num, column=5, value=location)
|
||||
ws.cell(row=row_num, column=6, value=satellite_info)
|
||||
ws.cell(row=row_num, column=7, value=direct_channel)
|
||||
ws.cell(row=row_num, column=8, value=reverse_channel)
|
||||
ws.cell(row=row_num, column=9, value=transfer)
|
||||
ws.cell(row=row_num, column=10, value=objitem_count)
|
||||
ws.cell(row=row_num, column=11, value='-') # Дата (пока не заполняется)
|
||||
ws.cell(row=row_num, column=12, value=mirrors_str)
|
||||
ws.cell(row=row_num, column=13, value='') # СКО не заполняется
|
||||
ws.cell(row=row_num, column=14, value='') # Примечание не заполняется
|
||||
ws.cell(row=row_num, column=15, value=operator_name)
|
||||
|
||||
row_num += 1
|
||||
|
||||
# Автоширина колонок
|
||||
for column in ws.columns:
|
||||
max_length = 0
|
||||
column_letter = column[0].column_letter
|
||||
for cell in column:
|
||||
try:
|
||||
if len(str(cell.value)) > max_length:
|
||||
max_length = len(str(cell.value))
|
||||
except:
|
||||
pass
|
||||
adjusted_width = min(max_length + 2, 50)
|
||||
ws.column_dimensions[column_letter].width = adjusted_width
|
||||
|
||||
# Сохраняем в BytesIO
|
||||
output = BytesIO()
|
||||
wb.save(output)
|
||||
output.seek(0)
|
||||
|
||||
# Возвращаем файл
|
||||
response = HttpResponse(
|
||||
output.read(),
|
||||
content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
)
|
||||
response['Content-Disposition'] = f'attachment; filename="kubsat_{datetime.now().strftime("%Y%m%d_%H%M%S")}.xlsx"'
|
||||
|
||||
return response
|
||||
@@ -8,7 +8,7 @@ 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.db.models import Count, Prefetch, Q
|
||||
from django.http import JsonResponse
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse
|
||||
@@ -234,10 +234,109 @@ class SourceListView(LoginRequiredMixin, View):
|
||||
objitem_filter_q &= Q(source_objitems__geo_obj__coords__within=polygon_geom)
|
||||
has_objitem_filter = True
|
||||
|
||||
# Build filtered objitems queryset for prefetch
|
||||
from ..models import ObjItem
|
||||
filtered_objitems_qs = ObjItem.objects.select_related(
|
||||
'parameter_obj',
|
||||
'parameter_obj__id_satellite',
|
||||
'parameter_obj__polarization',
|
||||
'parameter_obj__modulation',
|
||||
'parameter_obj__standard',
|
||||
'geo_obj',
|
||||
'lyngsat_source',
|
||||
'lyngsat_source__id_satellite',
|
||||
'lyngsat_source__polarization',
|
||||
'lyngsat_source__modulation',
|
||||
'lyngsat_source__standard',
|
||||
'transponder',
|
||||
'created_by',
|
||||
'created_by__user',
|
||||
'updated_by',
|
||||
'updated_by__user',
|
||||
).prefetch_related(
|
||||
'geo_obj__mirrors',
|
||||
)
|
||||
|
||||
# Apply the same filters to prefetch queryset
|
||||
if search_by_name:
|
||||
filtered_objitems_qs = filtered_objitems_qs.filter(name__icontains=search_query)
|
||||
if geo_date_from:
|
||||
try:
|
||||
geo_date_from_obj = datetime.strptime(geo_date_from, "%Y-%m-%d")
|
||||
filtered_objitems_qs = filtered_objitems_qs.filter(geo_obj__timestamp__gte=geo_date_from_obj)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if geo_date_to:
|
||||
try:
|
||||
from datetime import timedelta
|
||||
geo_date_to_obj = datetime.strptime(geo_date_to, "%Y-%m-%d")
|
||||
geo_date_to_obj = geo_date_to_obj + timedelta(days=1)
|
||||
filtered_objitems_qs = filtered_objitems_qs.filter(geo_obj__timestamp__lt=geo_date_to_obj)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if selected_satellites:
|
||||
filtered_objitems_qs = filtered_objitems_qs.filter(parameter_obj__id_satellite_id__in=selected_satellites)
|
||||
if selected_polarizations:
|
||||
filtered_objitems_qs = filtered_objitems_qs.filter(parameter_obj__polarization_id__in=selected_polarizations)
|
||||
if selected_modulations:
|
||||
filtered_objitems_qs = filtered_objitems_qs.filter(parameter_obj__modulation_id__in=selected_modulations)
|
||||
if freq_min:
|
||||
try:
|
||||
freq_min_val = float(freq_min)
|
||||
filtered_objitems_qs = filtered_objitems_qs.filter(parameter_obj__frequency__gte=freq_min_val)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if freq_max:
|
||||
try:
|
||||
freq_max_val = float(freq_max)
|
||||
filtered_objitems_qs = filtered_objitems_qs.filter(parameter_obj__frequency__lte=freq_max_val)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if freq_range_min:
|
||||
try:
|
||||
freq_range_min_val = float(freq_range_min)
|
||||
filtered_objitems_qs = filtered_objitems_qs.filter(parameter_obj__freq_range__gte=freq_range_min_val)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if freq_range_max:
|
||||
try:
|
||||
freq_range_max_val = float(freq_range_max)
|
||||
filtered_objitems_qs = filtered_objitems_qs.filter(parameter_obj__freq_range__lte=freq_range_max_val)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if bod_velocity_min:
|
||||
try:
|
||||
bod_velocity_min_val = float(bod_velocity_min)
|
||||
filtered_objitems_qs = filtered_objitems_qs.filter(parameter_obj__bod_velocity__gte=bod_velocity_min_val)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if bod_velocity_max:
|
||||
try:
|
||||
bod_velocity_max_val = float(bod_velocity_max)
|
||||
filtered_objitems_qs = filtered_objitems_qs.filter(parameter_obj__bod_velocity__lte=bod_velocity_max_val)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if snr_min:
|
||||
try:
|
||||
snr_min_val = float(snr_min)
|
||||
filtered_objitems_qs = filtered_objitems_qs.filter(parameter_obj__snr__gte=snr_min_val)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if snr_max:
|
||||
try:
|
||||
snr_max_val = float(snr_max)
|
||||
filtered_objitems_qs = filtered_objitems_qs.filter(parameter_obj__snr__lte=snr_max_val)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if selected_mirrors:
|
||||
filtered_objitems_qs = filtered_objitems_qs.filter(geo_obj__mirrors__id__in=selected_mirrors)
|
||||
if polygon_geom:
|
||||
filtered_objitems_qs = filtered_objitems_qs.filter(geo_obj__coords__within=polygon_geom)
|
||||
|
||||
# Get all Source objects with query optimization
|
||||
# Using annotate to count ObjItems efficiently (single query with GROUP BY)
|
||||
# Using select_related for ForeignKey/OneToOne relationships to avoid N+1 queries
|
||||
# Using prefetch_related for reverse ForeignKey and ManyToMany relationships
|
||||
# Using Prefetch with filtered queryset to avoid N+1 queries in display loop
|
||||
sources = Source.objects.select_related(
|
||||
'info', # ForeignKey to ObjectInfo
|
||||
'created_by', # ForeignKey to CustomUser
|
||||
@@ -245,25 +344,8 @@ class SourceListView(LoginRequiredMixin, View):
|
||||
'updated_by', # ForeignKey to CustomUser
|
||||
'updated_by__user', # OneToOne to User
|
||||
).prefetch_related(
|
||||
# Prefetch related objitems with their nested relationships
|
||||
'source_objitems',
|
||||
'source_objitems__parameter_obj',
|
||||
'source_objitems__parameter_obj__id_satellite',
|
||||
'source_objitems__parameter_obj__polarization',
|
||||
'source_objitems__parameter_obj__modulation',
|
||||
'source_objitems__parameter_obj__standard',
|
||||
'source_objitems__geo_obj',
|
||||
'source_objitems__geo_obj__mirrors',
|
||||
'source_objitems__lyngsat_source',
|
||||
'source_objitems__lyngsat_source__id_satellite',
|
||||
'source_objitems__lyngsat_source__polarization',
|
||||
'source_objitems__lyngsat_source__modulation',
|
||||
'source_objitems__lyngsat_source__standard',
|
||||
'source_objitems__transponder',
|
||||
'source_objitems__created_by',
|
||||
'source_objitems__created_by__user',
|
||||
'source_objitems__updated_by',
|
||||
'source_objitems__updated_by__user',
|
||||
# Use Prefetch with filtered queryset
|
||||
Prefetch('source_objitems', queryset=filtered_objitems_qs, to_attr='filtered_objitems'),
|
||||
# Prefetch marks with their relationships
|
||||
'marks',
|
||||
'marks__created_by',
|
||||
@@ -525,76 +607,8 @@ class SourceListView(LoginRequiredMixin, View):
|
||||
coords_valid_str = format_coords_display(source.coords_valid)
|
||||
coords_reference_str = format_coords_display(source.coords_reference)
|
||||
|
||||
# Filter objitems for display (to get satellites and lyngsat info)
|
||||
objitems_to_display = source.source_objitems.all()
|
||||
|
||||
# Apply the same filters as in the count annotation
|
||||
if geo_date_from:
|
||||
try:
|
||||
geo_date_from_obj = datetime.strptime(geo_date_from, "%Y-%m-%d")
|
||||
objitems_to_display = objitems_to_display.filter(geo_obj__timestamp__gte=geo_date_from_obj)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if geo_date_to:
|
||||
try:
|
||||
from datetime import timedelta
|
||||
geo_date_to_obj = datetime.strptime(geo_date_to, "%Y-%m-%d")
|
||||
geo_date_to_obj = geo_date_to_obj + timedelta(days=1)
|
||||
objitems_to_display = objitems_to_display.filter(geo_obj__timestamp__lt=geo_date_to_obj)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if selected_satellites:
|
||||
objitems_to_display = objitems_to_display.filter(parameter_obj__id_satellite_id__in=selected_satellites)
|
||||
if selected_polarizations:
|
||||
objitems_to_display = objitems_to_display.filter(parameter_obj__polarization_id__in=selected_polarizations)
|
||||
if selected_modulations:
|
||||
objitems_to_display = objitems_to_display.filter(parameter_obj__modulation_id__in=selected_modulations)
|
||||
if freq_min:
|
||||
try:
|
||||
objitems_to_display = objitems_to_display.filter(parameter_obj__frequency__gte=float(freq_min))
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if freq_max:
|
||||
try:
|
||||
objitems_to_display = objitems_to_display.filter(parameter_obj__frequency__lte=float(freq_max))
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if freq_range_min:
|
||||
try:
|
||||
objitems_to_display = objitems_to_display.filter(parameter_obj__freq_range__gte=float(freq_range_min))
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if freq_range_max:
|
||||
try:
|
||||
objitems_to_display = objitems_to_display.filter(parameter_obj__freq_range__lte=float(freq_range_max))
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if bod_velocity_min:
|
||||
try:
|
||||
objitems_to_display = objitems_to_display.filter(parameter_obj__bod_velocity__gte=float(bod_velocity_min))
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if bod_velocity_max:
|
||||
try:
|
||||
objitems_to_display = objitems_to_display.filter(parameter_obj__bod_velocity__lte=float(bod_velocity_max))
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if snr_min:
|
||||
try:
|
||||
objitems_to_display = objitems_to_display.filter(parameter_obj__snr__gte=float(snr_min))
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if snr_max:
|
||||
try:
|
||||
objitems_to_display = objitems_to_display.filter(parameter_obj__snr__lte=float(snr_max))
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if selected_mirrors:
|
||||
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 pre-filtered objitems from Prefetch
|
||||
objitems_to_display = source.filtered_objitems
|
||||
|
||||
# Use annotated count (consistent with filtering)
|
||||
objitem_count = source.objitem_count
|
||||
|
||||
Reference in New Issue
Block a user