264 lines
11 KiB
Python
264 lines
11 KiB
Python
"""
|
||
Data import views (Excel, CSV, Transponders, VCH, etc.).
|
||
"""
|
||
from io import BytesIO
|
||
|
||
from django.contrib import messages
|
||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||
from django.http import HttpResponse
|
||
from django.shortcuts import redirect
|
||
from django.urls import reverse_lazy
|
||
from django.views import View
|
||
from django.views.generic import FormView
|
||
|
||
import pandas as pd
|
||
|
||
from ..forms import (
|
||
LoadCsvData,
|
||
LoadExcelData,
|
||
NewEventForm,
|
||
UploadFileForm,
|
||
UploadVchLoad,
|
||
VchLinkForm,
|
||
)
|
||
from ..mixins import FormMessageMixin
|
||
from ..utils import (
|
||
add_satellite_list,
|
||
compare_and_link_vch_load,
|
||
fill_data_from_df,
|
||
get_points_from_csv,
|
||
get_vch_load_from_html,
|
||
kub_report,
|
||
)
|
||
from mapsapp.utils import parse_transponders_from_xml
|
||
|
||
|
||
class AddSatellitesView(LoginRequiredMixin, View):
|
||
"""View for adding satellites to the database."""
|
||
|
||
def get(self, request):
|
||
add_satellite_list()
|
||
return redirect("mainapp:source_list")
|
||
|
||
|
||
class AddTranspondersView(LoginRequiredMixin, FormMessageMixin, FormView):
|
||
"""View for uploading and parsing transponder data from XML."""
|
||
|
||
template_name = "mainapp/transponders_upload.html"
|
||
form_class = UploadFileForm
|
||
success_message = "Файл успешно обработан"
|
||
error_message = "Форма заполнена некорректно"
|
||
|
||
def form_valid(self, form):
|
||
uploaded_file = self.request.FILES["file"]
|
||
try:
|
||
content = uploaded_file.read()
|
||
# Передаем текущего пользователя в функцию парсинга
|
||
stats = parse_transponders_from_xml(BytesIO(content), self.request.user.customuser)
|
||
|
||
# Формируем сообщение со статистикой
|
||
stats_message = (
|
||
f"<strong>Импорт завершён</strong><br>"
|
||
f"Спутники: создано {stats['satellites_created']}, "
|
||
f"обновлено {stats['satellites_updated']}, "
|
||
f"пропущено {stats['satellites_skipped']}, "
|
||
f"игнорировано {stats['satellites_ignored']}<br>"
|
||
f"Транспондеры: создано {stats['transponders_created']}, "
|
||
f"существующих {stats['transponders_existing']}"
|
||
)
|
||
|
||
if stats['errors']:
|
||
stats_message += f"<br><strong>Ошибок: {len(stats['errors'])}</strong>"
|
||
messages.warning(self.request, stats_message, extra_tags='persistent')
|
||
else:
|
||
messages.success(self.request, stats_message, extra_tags='persistent')
|
||
|
||
except ValueError as e:
|
||
messages.error(self.request, f"Ошибка при чтении таблиц: {e}")
|
||
return redirect("mainapp:add_trans")
|
||
except Exception as e:
|
||
messages.error(self.request, f"Неизвестная ошибка: {e}")
|
||
return redirect("mainapp:add_trans")
|
||
return super().form_valid(form)
|
||
|
||
def get_success_url(self):
|
||
return reverse_lazy("mainapp:add_trans")
|
||
|
||
|
||
class LoadExcelDataView(LoginRequiredMixin, FormMessageMixin, FormView):
|
||
"""View for loading data from Excel files."""
|
||
|
||
template_name = "mainapp/add_data_from_excel.html"
|
||
form_class = LoadExcelData
|
||
error_message = "Форма заполнена некорректно"
|
||
|
||
def form_valid(self, form):
|
||
uploaded_file = self.request.FILES["file"]
|
||
selected_sat = form.cleaned_data["sat_choice"]
|
||
number = form.cleaned_data["number_input"]
|
||
is_automatic = form.cleaned_data.get("is_automatic", False)
|
||
|
||
try:
|
||
import io
|
||
|
||
df = pd.read_excel(io.BytesIO(uploaded_file.read()))
|
||
if number > 0:
|
||
df = df.head(number)
|
||
result = fill_data_from_df(df, selected_sat, self.request.user.customuser, is_automatic)
|
||
|
||
# Формируем сообщение об успехе
|
||
if is_automatic:
|
||
success_msg = f"Данные успешно загружены как автоматические! Добавлено точек: {result['added']}"
|
||
else:
|
||
success_msg = f"Данные успешно загружены! Создано источников: {result['new_sources']}, добавлено точек: {result['added']}"
|
||
|
||
if result['skipped'] > 0:
|
||
success_msg += f", пропущено дубликатов: {result['skipped']}"
|
||
|
||
messages.success(self.request, success_msg)
|
||
|
||
# Показываем ошибки, если они есть
|
||
if result['errors']:
|
||
error_count = len(result['errors'])
|
||
messages.warning(
|
||
self.request,
|
||
f"Обнаружено ошибок: {error_count}. Первые ошибки: " + "; ".join(result['errors'][:5])
|
||
)
|
||
|
||
except Exception as e:
|
||
messages.error(self.request, f"Ошибка при обработке файла: {str(e)}")
|
||
|
||
return redirect("mainapp:load_excel_data")
|
||
|
||
def get_success_url(self):
|
||
return reverse_lazy("mainapp:load_excel_data")
|
||
|
||
|
||
class LoadCsvDataView(LoginRequiredMixin, FormMessageMixin, FormView):
|
||
"""View for loading data from CSV files."""
|
||
|
||
template_name = "mainapp/add_data_from_csv.html"
|
||
form_class = LoadCsvData
|
||
success_message = "Данные успешно загружены!"
|
||
error_message = "Форма заполнена некорректно"
|
||
|
||
def form_valid(self, form):
|
||
uploaded_file = self.request.FILES["file"]
|
||
is_automatic = form.cleaned_data.get("is_automatic", False)
|
||
|
||
try:
|
||
content = uploaded_file.read()
|
||
if isinstance(content, bytes):
|
||
content = content.decode("utf-8")
|
||
|
||
result = get_points_from_csv(content, self.request.user.customuser, is_automatic)
|
||
|
||
# Формируем сообщение об успехе
|
||
if is_automatic:
|
||
success_msg = f"Данные успешно загружены как автоматические! Добавлено точек: {result['added']}"
|
||
else:
|
||
success_msg = f"Данные успешно загружены! Создано источников: {result['new_sources']}, добавлено точек: {result['added']}"
|
||
|
||
if result['skipped'] > 0:
|
||
success_msg += f", пропущено дубликатов: {result['skipped']}"
|
||
|
||
messages.success(self.request, success_msg)
|
||
|
||
# Показываем ошибки, если они есть
|
||
if result['errors']:
|
||
error_count = len(result['errors'])
|
||
messages.warning(
|
||
self.request,
|
||
f"Обнаружено ошибок: {error_count}. Первые ошибки: " + "; ".join(result['errors'][:5])
|
||
)
|
||
|
||
except Exception as e:
|
||
messages.error(self.request, f"Ошибка при обработке файла: {str(e)}")
|
||
return redirect("mainapp:load_csv_data")
|
||
|
||
return super().form_valid(form)
|
||
|
||
def get_success_url(self):
|
||
return reverse_lazy("mainapp:load_csv_data")
|
||
|
||
|
||
class UploadVchLoadView(LoginRequiredMixin, FormMessageMixin, FormView):
|
||
"""View for uploading VCH load data from HTML files."""
|
||
|
||
template_name = "mainapp/upload_html.html"
|
||
form_class = UploadVchLoad
|
||
success_message = "Файл успешно обработан"
|
||
error_message = "Форма заполнена некорректно"
|
||
|
||
def form_valid(self, form):
|
||
selected_sat = form.cleaned_data["sat_choice"]
|
||
uploaded_file = self.request.FILES["file"]
|
||
try:
|
||
get_vch_load_from_html(uploaded_file, selected_sat)
|
||
except ValueError as e:
|
||
messages.error(self.request, f"Ошибка при чтении таблиц: {e}")
|
||
return redirect("mainapp:vch_load")
|
||
except Exception as e:
|
||
messages.error(self.request, f"Неизвестная ошибка: {e}")
|
||
return redirect("mainapp:vch_load")
|
||
|
||
return super().form_valid(form)
|
||
|
||
def get_success_url(self):
|
||
return reverse_lazy("mainapp:vch_load")
|
||
|
||
|
||
class LinkVchSigmaView(LoginRequiredMixin, FormView):
|
||
"""View for linking VCH data with Sigma parameters."""
|
||
|
||
template_name = "mainapp/link_vch.html"
|
||
form_class = VchLinkForm
|
||
|
||
def form_valid(self, form):
|
||
# value1 is no longer used - frequency tolerance is determined automatically
|
||
freq_range = form.cleaned_data["value2"]
|
||
sat_id = form.cleaned_data["sat_choice"]
|
||
|
||
# Pass 0 for eps_freq and ku_range as they are not used
|
||
count_all, link_count = compare_and_link_vch_load(sat_id, 0, freq_range, 0)
|
||
|
||
messages.success(
|
||
self.request, f"Привязано {link_count} из {count_all} объектов"
|
||
)
|
||
return redirect("mainapp:link_vch_sigma")
|
||
|
||
def form_invalid(self, form):
|
||
return self.render_to_response(self.get_context_data(form=form))
|
||
|
||
|
||
class ProcessKubsatView(LoginRequiredMixin, FormMessageMixin, FormView):
|
||
"""View for processing Kubsat event data."""
|
||
|
||
template_name = "mainapp/process_kubsat.html"
|
||
form_class = NewEventForm
|
||
error_message = "Форма заполнена некорректно"
|
||
|
||
def form_valid(self, form):
|
||
uploaded_file = self.request.FILES["file"]
|
||
try:
|
||
content = uploaded_file.read()
|
||
df = kub_report(BytesIO(content))
|
||
output = BytesIO()
|
||
with pd.ExcelWriter(output, engine="openpyxl") as writer:
|
||
df.to_excel(writer, index=False, sheet_name="Результат")
|
||
output.seek(0)
|
||
|
||
response = HttpResponse(
|
||
output.getvalue(),
|
||
content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||
)
|
||
response["Content-Disposition"] = (
|
||
'attachment; filename="kubsat_report.xlsx"'
|
||
)
|
||
|
||
messages.success(self.request, "Событие успешно обработано!")
|
||
return response
|
||
except Exception as e:
|
||
messages.error(self.request, f"Ошибка при обработке файла: {str(e)}")
|
||
return redirect("mainapp:kubsat_excel")
|