Исправил отображения объектов в источниках

This commit is contained in:
2025-11-16 00:16:50 +03:00
parent 9a816e62c2
commit d9cb243388
13 changed files with 1198 additions and 48 deletions

View File

@@ -30,6 +30,7 @@ from .lyngsat import (
FillLyngsatDataView,
LyngsatTaskStatusView,
ClearLyngsatCacheView,
UnlinkAllLyngsatSourcesView,
)
from .source import SourceListView, SourceUpdateView, SourceDeleteView, DeleteSelectedSourcesView
from .transponder import (
@@ -78,6 +79,7 @@ __all__ = [
'FillLyngsatDataView',
'LyngsatTaskStatusView',
'ClearLyngsatCacheView',
'UnlinkAllLyngsatSourcesView',
# Source
'SourceListView',
'SourceUpdateView',

View File

@@ -186,7 +186,13 @@ class SourceObjItemsAPIView(LoginRequiredMixin, View):
'source_objitems__parameter_obj__id_satellite',
'source_objitems__parameter_obj__polarization',
'source_objitems__parameter_obj__modulation',
'source_objitems__geo_obj'
'source_objitems__parameter_obj__standard',
'source_objitems__geo_obj',
'source_objitems__geo_obj__mirrors',
'source_objitems__lyngsat_source',
'source_objitems__transponder',
'source_objitems__created_by__user',
'source_objitems__updated_by__user'
).get(id=source_id)
# Get all related ObjItems, sorted by created_at
@@ -202,9 +208,12 @@ class SourceObjItemsAPIView(LoginRequiredMixin, View):
polarization = '-'
bod_velocity = '-'
modulation = '-'
standard = '-'
snr = '-'
parameter_id = None
if param:
parameter_id = param.id
if hasattr(param, 'id_satellite') and param.id_satellite:
satellite_name = param.id_satellite.name
frequency = f"{param.frequency:.3f}" if param.frequency is not None else '-'
@@ -214,6 +223,8 @@ class SourceObjItemsAPIView(LoginRequiredMixin, View):
bod_velocity = f"{param.bod_velocity:.0f}" if param.bod_velocity is not None else '-'
if hasattr(param, 'modulation') and param.modulation:
modulation = param.modulation.name
if hasattr(param, 'standard') and param.standard:
standard = param.standard.name
snr = f"{param.snr:.0f}" if param.snr is not None else '-'
# Get geo data
@@ -235,6 +246,56 @@ class SourceObjItemsAPIView(LoginRequiredMixin, View):
lat = f"{latitude}N" if latitude > 0 else f"{abs(latitude)}S"
geo_coords = f"{lat} {lon}"
# Get created/updated info
created_at = '-'
if objitem.created_at:
local_time = timezone.localtime(objitem.created_at)
created_at = local_time.strftime("%d.%m.%Y %H:%M")
updated_at = '-'
if objitem.updated_at:
local_time = timezone.localtime(objitem.updated_at)
updated_at = local_time.strftime("%d.%m.%Y %H:%M")
created_by = str(objitem.created_by) if objitem.created_by else '-'
updated_by = str(objitem.updated_by) if objitem.updated_by else '-'
# Check for LyngSat
has_lyngsat = hasattr(objitem, 'lyngsat_source') and objitem.lyngsat_source is not None
lyngsat_id = objitem.lyngsat_source.id if has_lyngsat else None
# Check for Transponder
has_transponder = hasattr(objitem, 'transponder') and objitem.transponder is not None
transponder_id = objitem.transponder.id if has_transponder else None
transponder_info = '-'
if has_transponder:
try:
downlink = objitem.transponder.downlink if objitem.transponder.downlink else '-'
freq_range_t = objitem.transponder.frequency_range if objitem.transponder.frequency_range else '-'
transponder_info = f"{downlink}:{freq_range_t}"
except Exception:
transponder_info = '-'
# Check for Sigma
has_sigma = False
sigma_info = '-'
if param and hasattr(param, 'sigma_parameter'):
sigma_count = param.sigma_parameter.count()
if sigma_count > 0:
has_sigma = True
sigma_info = f"{sigma_count}"
# Get comment, is_average, and mirrors from geo_obj
comment = '-'
is_average = '-'
mirrors = '-'
if hasattr(objitem, 'geo_obj') and objitem.geo_obj:
comment = objitem.geo_obj.comment or '-'
is_average = 'Да' if objitem.geo_obj.is_average else 'Нет'
# Get mirrors list
mirrors_list = list(objitem.geo_obj.mirrors.values_list('name', flat=True))
mirrors = ', '.join(mirrors_list) if mirrors_list else '-'
objitems_data.append({
'id': objitem.id,
'name': objitem.name or '-',
@@ -244,10 +305,26 @@ class SourceObjItemsAPIView(LoginRequiredMixin, View):
'polarization': polarization,
'bod_velocity': bod_velocity,
'modulation': modulation,
'standard': standard,
'snr': snr,
'geo_timestamp': geo_timestamp,
'geo_location': geo_location,
'geo_coords': geo_coords
'geo_coords': geo_coords,
'created_at': created_at,
'updated_at': updated_at,
'created_by': created_by,
'updated_by': updated_by,
'comment': comment,
'is_average': is_average,
'has_lyngsat': has_lyngsat,
'lyngsat_id': lyngsat_id,
'has_transponder': has_transponder,
'transponder_id': transponder_id,
'transponder_info': transponder_info,
'has_sigma': has_sigma,
'sigma_info': sigma_info,
'parameter_id': parameter_id,
'mirrors': mirrors,
})
return JsonResponse({

View File

@@ -46,22 +46,30 @@ class LinkLyngsatSourcesView(LoginRequiredMixin, FormMessageMixin, FormView):
param = objitem.parameter_obj
# Round object frequency
# Round object frequency to 1 decimal place
if param.frequency:
rounded_freq = round(param.frequency, 0) # Round to integer
rounded_freq = round(param.frequency, 1) # Round to 1 decimal place
# Find matching LyngSat source
# Compare by rounded frequency and polarization
# Compare by rounded frequency (with tolerance) and polarization
# LyngSat frequencies are also rounded to 1 decimal place for comparison
lyngsat_sources = LyngSat.objects.filter(
id_satellite=param.id_satellite,
polarization=param.polarization,
frequency__gte=rounded_freq - frequency_tolerance,
frequency__lte=rounded_freq + frequency_tolerance
).order_by('frequency')
polarization=param.polarization
).select_related('id_satellite', 'polarization')
if lyngsat_sources.exists():
# Take first matching source
objitem.lyngsat_source = lyngsat_sources.first()
# Filter by rounded frequency with tolerance
matching_sources = []
for lyngsat in lyngsat_sources:
if lyngsat.frequency:
rounded_lyngsat_freq = round(lyngsat.frequency, 1)
if abs(rounded_lyngsat_freq - rounded_freq) <= frequency_tolerance:
matching_sources.append(lyngsat)
if matching_sources:
# Take first matching source (sorted by frequency difference)
matching_sources.sort(key=lambda x: abs(round(x.frequency, 1) - rounded_freq))
objitem.lyngsat_source = matching_sources[0]
objitem.save(update_fields=['lyngsat_source'])
linked_count += 1
@@ -159,3 +167,35 @@ class ClearLyngsatCacheView(LoginRequiredMixin, View):
def get(self, request):
"""Cache management page."""
return render(request, 'mainapp/clear_lyngsat_cache.html')
class UnlinkAllLyngsatSourcesView(LoginRequiredMixin, View):
"""View for unlinking all LyngSat sources from ObjItems."""
def post(self, request):
"""Unlink all LyngSat sources."""
try:
# Count objects with LyngSat sources before unlinking
linked_count = ObjItem.objects.filter(lyngsat_source__isnull=False).count()
# Unlink all LyngSat sources
ObjItem.objects.filter(lyngsat_source__isnull=False).update(lyngsat_source=None)
messages.success(
request,
f"Успешно отвязано {linked_count} объектов от источников LyngSat"
)
except Exception as e:
messages.error(request, f"Ошибка при отвязке источников: {str(e)}")
return redirect('mainapp:actions')
def get(self, request):
"""Show confirmation page."""
# Count objects with LyngSat sources
linked_count = ObjItem.objects.filter(lyngsat_source__isnull=False).count()
context = {
'linked_count': linked_count
}
return render(request, 'mainapp/unlink_lyngsat_confirm.html', context)

View File

@@ -35,6 +35,7 @@ class SourceListView(LoginRequiredMixin, View):
has_coords_kupsat = request.GET.get("has_coords_kupsat")
has_coords_valid = request.GET.get("has_coords_valid")
has_coords_reference = request.GET.get("has_coords_reference")
has_lyngsat = request.GET.get("has_lyngsat")
objitem_count_min = request.GET.get("objitem_count_min", "").strip()
objitem_count_max = request.GET.get("objitem_count_max", "").strip()
date_from = request.GET.get("date_from", "").strip()
@@ -86,6 +87,14 @@ class SourceListView(LoginRequiredMixin, View):
elif has_coords_reference == "0":
sources = sources.filter(coords_reference__isnull=True)
# Filter by LyngSat presence
if has_lyngsat == "1":
sources = sources.filter(source_objitems__lyngsat_source__isnull=False).distinct()
elif has_lyngsat == "0":
sources = sources.filter(
~Q(source_objitems__lyngsat_source__isnull=False)
).distinct()
# Filter by ObjItem count
if objitem_count_min:
try:
@@ -155,6 +164,8 @@ class SourceListView(LoginRequiredMixin, View):
# Prepare data for display
processed_sources = []
has_any_lyngsat = False # Track if any source has LyngSat data
for source in page_obj:
# Format coordinates
def format_coords(point):
@@ -174,12 +185,21 @@ class SourceListView(LoginRequiredMixin, View):
# Get count of related ObjItems
objitem_count = source.objitem_count
# Get satellites for this source
# Get satellites for this source and check for LyngSat
satellite_names = set()
has_lyngsat = False
lyngsat_id = None
for objitem in source.source_objitems.all():
if hasattr(objitem, 'parameter_obj') and objitem.parameter_obj:
if hasattr(objitem.parameter_obj, 'id_satellite') and objitem.parameter_obj.id_satellite:
satellite_names.add(objitem.parameter_obj.id_satellite.name)
# Check if any objitem has LyngSat
if hasattr(objitem, 'lyngsat_source') and objitem.lyngsat_source:
has_lyngsat = True
lyngsat_id = objitem.lyngsat_source.id
has_any_lyngsat = True
satellite_str = ", ".join(sorted(satellite_names)) if satellite_names else "-"
@@ -193,6 +213,8 @@ class SourceListView(LoginRequiredMixin, View):
'satellite': satellite_str,
'created_at': source.created_at,
'updated_at': source.updated_at,
'has_lyngsat': has_lyngsat,
'lyngsat_id': lyngsat_id,
})
# Prepare context for template
@@ -207,6 +229,8 @@ class SourceListView(LoginRequiredMixin, View):
'has_coords_kupsat': has_coords_kupsat,
'has_coords_valid': has_coords_valid,
'has_coords_reference': has_coords_reference,
'has_lyngsat': has_lyngsat,
'has_any_lyngsat': has_any_lyngsat,
'objitem_count_min': objitem_count_min,
'objitem_count_max': objitem_count_max,
'date_from': date_from,