""" 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 if param.frequency: rounded_freq = round(param.frequency, 0) # Round to integer # Find matching LyngSat source # Compare by rounded frequency and polarization 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') if lyngsat_sources.exists(): # Take first matching source objitem.lyngsat_source = lyngsat_sources.first() 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')