Files
dbstorage/dbapp/mainapp/views/lyngsat.py

202 lines
8.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
LyngSat related views for data synchronization and linking.
"""
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import redirect, render
from django.urls import reverse_lazy
from django.views import View
from django.views.generic import FormView
from ..forms import FillLyngsatDataForm, LinkLyngsatForm
from ..mixins import FormMessageMixin
from ..models import ObjItem
class LinkLyngsatSourcesView(LoginRequiredMixin, FormMessageMixin, FormView):
"""View for linking LyngSat sources to objects."""
template_name = "mainapp/link_lyngsat.html"
form_class = LinkLyngsatForm
success_message = "Привязка источников LyngSat завершена"
error_message = "Ошибка при привязке источников"
def form_valid(self, form):
from lyngsatapp.models import LyngSat
satellites = form.cleaned_data.get("satellites")
frequency_tolerance = form.cleaned_data.get("frequency_tolerance", 0.5)
# If satellites not selected, process all
if satellites:
objitems = ObjItem.objects.filter(
parameter_obj__id_satellite__in=satellites
).select_related('parameter_obj', 'parameter_obj__polarization')
else:
objitems = ObjItem.objects.filter(
parameter_obj__isnull=False
).select_related('parameter_obj', 'parameter_obj__polarization')
linked_count = 0
total_count = objitems.count()
for objitem in objitems:
if not hasattr(objitem, 'parameter_obj') or not objitem.parameter_obj:
continue
param = objitem.parameter_obj
# Round object frequency to 1 decimal place
if param.frequency:
rounded_freq = round(param.frequency, 1) # Round to 1 decimal place
# Find matching LyngSat source
# 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
).select_related('id_satellite', 'polarization')
# 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
messages.success(
self.request,
f"Привязано {linked_count} из {total_count} объектов к источникам LyngSat"
)
return redirect("mainapp:link_lyngsat")
def form_invalid(self, form):
return self.render_to_response(self.get_context_data(form=form))
class FillLyngsatDataView(LoginRequiredMixin, FormMessageMixin, FormView):
"""
View for filling data from Lyngsat.
Allows selecting satellites and regions for parsing data from Lyngsat website.
Starts asynchronous Celery task for processing.
"""
template_name = "mainapp/fill_lyngsat_data.html"
form_class = FillLyngsatDataForm
success_url = reverse_lazy("mainapp:lyngsat_task_status")
error_message = "Форма заполнена некорректно"
def form_valid(self, form):
satellites = form.cleaned_data["satellites"]
regions = form.cleaned_data["regions"]
use_cache = form.cleaned_data.get("use_cache", True)
force_refresh = form.cleaned_data.get("force_refresh", False)
# Get satellite names
target_sats = [sat.name for sat in satellites]
try:
from lyngsatapp.tasks import fill_lyngsat_data_task
# Start asynchronous task with caching parameters
task = fill_lyngsat_data_task.delay(
target_sats,
regions,
force_refresh=force_refresh,
use_cache=use_cache
)
cache_status = "без кеша" if not use_cache else ("с обновлением кеша" if force_refresh else "с кешированием")
messages.success(
self.request,
f"Задача запущена ({cache_status})! ID задачи: {task.id}. "
"Вы будете перенаправлены на страницу отслеживания прогресса."
)
# Redirect to task status page
return redirect('mainapp:lyngsat_task_status', task_id=task.id)
except Exception as e:
messages.error(self.request, f"Ошибка при запуске задачи: {str(e)}")
return redirect("mainapp:fill_lyngsat_data")
class LyngsatTaskStatusView(LoginRequiredMixin, View):
"""View for tracking Lyngsat data filling task status."""
template_name = "mainapp/lyngsat_task_status.html"
def get(self, request, task_id=None):
context = {
'task_id': task_id
}
return render(request, self.template_name, context)
class ClearLyngsatCacheView(LoginRequiredMixin, View):
"""View for clearing LyngSat cache."""
def post(self, request):
from lyngsatapp.tasks import clear_cache_task
cache_type = request.POST.get('cache_type', 'all')
try:
# Start cache clearing task
task = clear_cache_task.delay(cache_type)
messages.success(
request,
f"Задача очистки кеша ({cache_type}) запущена! ID задачи: {task.id}"
)
except Exception as e:
messages.error(request, f"Ошибка при запуске задачи очистки кеша: {str(e)}")
return redirect(request.META.get('HTTP_REFERER', 'mainapp:home'))
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)