Добавил форму с предосмотром и редактированием
This commit is contained in:
@@ -6,10 +6,13 @@ from django.contrib.admin.views.decorators import staff_member_required
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views import View
|
||||
from django.views.generic import TemplateView, FormView
|
||||
from django.views.generic import TemplateView, FormView, UpdateView, DeleteView, CreateView
|
||||
from django.contrib.auth.mixins import UserPassesTestMixin, LoginRequiredMixin
|
||||
from django.contrib.auth import logout
|
||||
from django.forms import inlineformset_factory, modelformset_factory
|
||||
from django.db import models
|
||||
from django.urls import reverse_lazy
|
||||
from django.contrib.gis.geos import Point
|
||||
import pandas as pd
|
||||
from .utils import (
|
||||
fill_data_from_df,
|
||||
@@ -20,10 +23,21 @@ from .utils import (
|
||||
kub_report
|
||||
)
|
||||
from mapsapp.utils import parse_transponders_from_json, parse_transponders_from_xml
|
||||
from .forms import LoadExcelData, LoadCsvData, UploadFileForm, VchLinkForm, UploadVchLoad, NewEventForm
|
||||
from .forms import (
|
||||
LoadExcelData,
|
||||
LoadCsvData,
|
||||
UploadFileForm,
|
||||
VchLinkForm,
|
||||
UploadVchLoad,
|
||||
NewEventForm,
|
||||
ObjItemForm,
|
||||
ParameterForm,
|
||||
GeoForm
|
||||
)
|
||||
from .models import ObjItem
|
||||
from .clusters import get_clusters
|
||||
from io import BytesIO
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
|
||||
@@ -93,7 +107,7 @@ class LoadExcelDataView(LoginRequiredMixin, FormView):
|
||||
df = pd.read_excel(io.BytesIO(uploaded_file.read()))
|
||||
if number > 0:
|
||||
df = df.head(number)
|
||||
result = fill_data_from_df(df, selected_sat)
|
||||
result = fill_data_from_df(df, selected_sat, self.request.user.customuser)
|
||||
|
||||
messages.success(self.request, f"Данные успешно загружены! Обработано строк: {result}")
|
||||
return redirect('load_excel_data')
|
||||
@@ -151,7 +165,7 @@ class LoadCsvDataView(LoginRequiredMixin, FormView):
|
||||
if isinstance(content, bytes):
|
||||
content = content.decode('utf-8')
|
||||
|
||||
get_points_from_csv(content)
|
||||
get_points_from_csv(content, self.request.user.customuser)
|
||||
messages.success(self.request, f"Данные успешно загружены!")
|
||||
return redirect('load_csv_data')
|
||||
except Exception as e:
|
||||
@@ -331,7 +345,7 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
try:
|
||||
items_per_page = int(items_per_page)
|
||||
except ValueError:
|
||||
items_per_page = 25
|
||||
items_per_page = 50
|
||||
|
||||
# Only filter objects by selected satellite if provided (no data shown by default)
|
||||
objects = ObjItem.objects.none() # Initially empty
|
||||
@@ -348,11 +362,11 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
|
||||
# Start with the basic filter if any satellites are selected
|
||||
if selected_satellites:
|
||||
# Start with the basic filter
|
||||
# Start with the basic filter - optimized with prefetch_related for all related objects
|
||||
objects = ObjItem.objects.select_related(
|
||||
'id_user_add__user',
|
||||
'geo_obj',
|
||||
'updated_by__user'
|
||||
'updated_by__user',
|
||||
'created_by__user',
|
||||
).prefetch_related(
|
||||
'parameters_obj__id_satellite',
|
||||
'parameters_obj__polarization',
|
||||
@@ -362,9 +376,9 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
else:
|
||||
# If no satellites are selected, start with all objects
|
||||
objects = ObjItem.objects.select_related(
|
||||
'id_user_add__user',
|
||||
'geo_obj',
|
||||
'updated_by__user'
|
||||
'updated_by__user',
|
||||
'created_by__user',
|
||||
).prefetch_related(
|
||||
'parameters_obj__id_satellite',
|
||||
'parameters_obj__polarization',
|
||||
@@ -468,8 +482,13 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
# Prepare the data to include calculated fields for the template
|
||||
processed_objects = []
|
||||
for obj in page_obj:
|
||||
# Get the first parameter
|
||||
param = obj.parameters_obj.first() if obj.parameters_obj.exists() else None
|
||||
# Get the first parameter using the prefetched relation to avoid additional queries
|
||||
param = None
|
||||
if hasattr(obj, 'parameters_obj') and obj.parameters_obj.all():
|
||||
# Get parameters from the prefetched queryset without triggering new query
|
||||
param_list = list(obj.parameters_obj.all())
|
||||
if param_list:
|
||||
param = param_list[0] # Get first parameter without additional query
|
||||
|
||||
# Process geo coordinates
|
||||
geo_coords = "-"
|
||||
@@ -518,22 +537,51 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
if obj.geo_obj.distance_kup_valid is not None:
|
||||
distance_kup_valid = f"{obj.geo_obj.distance_kup_valid:.3f}"
|
||||
|
||||
# Extract related object data to avoid additional queries in template
|
||||
satellite_name = "-"
|
||||
frequency = "-"
|
||||
freq_range = "-"
|
||||
polarization_name = "-"
|
||||
bod_velocity = "-"
|
||||
modulation_name = "-"
|
||||
snr = "-"
|
||||
|
||||
if param:
|
||||
# Get satellite data directly to avoid additional query
|
||||
if hasattr(param, 'id_satellite') and param.id_satellite:
|
||||
satellite_name = param.id_satellite.name if hasattr(param.id_satellite, 'name') else "-"
|
||||
|
||||
# Get parameter values directly
|
||||
frequency = f"{param.frequency:.3f}" if param.frequency is not None else "-"
|
||||
freq_range = f"{param.freq_range:.3f}" if param.freq_range is not None else "-"
|
||||
bod_velocity = f"{param.bod_velocity:.0f}" if param.bod_velocity is not None else "-"
|
||||
snr = f"{param.snr:.0f}" if param.snr is not None else "-"
|
||||
|
||||
# Get polarization name directly to avoid additional query
|
||||
if hasattr(param, 'polarization') and param.polarization:
|
||||
polarization_name = param.polarization.name if hasattr(param.polarization, 'name') else "-"
|
||||
|
||||
# Get modulation name directly to avoid additional query
|
||||
if hasattr(param, 'modulation') and param.modulation:
|
||||
modulation_name = param.modulation.name if hasattr(param.modulation, 'name') else "-"
|
||||
|
||||
processed_objects.append({
|
||||
'id': obj.id,
|
||||
'name': obj.name or "-",
|
||||
'satellite_name': param.id_satellite.name if param and param.id_satellite else "-",
|
||||
'frequency': f"{param.frequency:.3f}" if param and param.frequency else "-",
|
||||
'freq_range': f"{param.freq_range:.3f}" if param and param.freq_range else "-",
|
||||
'polarization': param.polarization.name if param and param.polarization else "-",
|
||||
'bod_velocity': f"{param.bod_velocity:.0f}" if param and param.bod_velocity else "-",
|
||||
'modulation': param.modulation.name if param and param.modulation else "-",
|
||||
'snr': f"{param.snr:.0f}" if param and param.snr else "-",
|
||||
'satellite_name': satellite_name,
|
||||
'frequency': frequency,
|
||||
'freq_range': freq_range,
|
||||
'polarization': polarization_name,
|
||||
'bod_velocity': bod_velocity,
|
||||
'modulation': modulation_name,
|
||||
'snr': snr,
|
||||
'geo_coords': geo_coords,
|
||||
'kupsat_coords': kupsat_coords,
|
||||
'valid_coords': valid_coords,
|
||||
'distance_geo_kup': distance_geo_kup,
|
||||
'distance_geo_valid': distance_geo_valid,
|
||||
'distance_kup_valid': distance_kup_valid,
|
||||
'updated_by': obj.updated_by if obj.updated_by else '-',
|
||||
'obj': obj
|
||||
})
|
||||
|
||||
@@ -571,4 +619,209 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
'full_width_page': True,
|
||||
}
|
||||
|
||||
return render(request, 'mainapp/objitem_list.html', context)
|
||||
return render(request, 'mainapp/objitem_list.html', context)
|
||||
|
||||
class ObjItemUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
|
||||
model = ObjItem
|
||||
form_class = ObjItemForm
|
||||
template_name = 'mainapp/objitem_form.html'
|
||||
success_url = reverse_lazy('home')
|
||||
|
||||
def test_func(self):
|
||||
return self.request.user.customuser.role in ['admin', 'moderator']
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
# Добавляем контекст для карты
|
||||
context['LEAFLET_CONFIG'] = {
|
||||
'DEFAULT_CENTER': (55.75, 37.62),
|
||||
'DEFAULT_ZOOM': 5,
|
||||
}
|
||||
|
||||
# Остальной контекст остается без изменений
|
||||
ParameterFormSet = modelformset_factory(
|
||||
Parameter,
|
||||
form=ParameterForm,
|
||||
extra=0,
|
||||
can_delete=True
|
||||
)
|
||||
|
||||
if self.object:
|
||||
parameter_queryset = self.object.parameters_obj.all()
|
||||
context['parameter_forms'] = ParameterFormSet(
|
||||
queryset=parameter_queryset,
|
||||
prefix='parameters'
|
||||
)
|
||||
|
||||
if hasattr(self.object, 'geo_obj'):
|
||||
context['geo_form'] = GeoForm(instance=self.object.geo_obj, prefix='geo')
|
||||
else:
|
||||
context['geo_form'] = GeoForm(prefix='geo')
|
||||
else:
|
||||
context['parameter_forms'] = ParameterFormSet(
|
||||
queryset=Parameter.objects.none(),
|
||||
prefix='parameters'
|
||||
)
|
||||
context['geo_form'] = GeoForm(prefix='geo')
|
||||
|
||||
return context
|
||||
|
||||
def form_valid(self, form):
|
||||
context = self.get_context_data()
|
||||
parameter_forms = context['parameter_forms']
|
||||
geo_form = context['geo_form']
|
||||
|
||||
# Сохраняем основной объект
|
||||
self.object = form.save(commit=False)
|
||||
self.object.updated_by = self.request.user.customuser
|
||||
self.object.save()
|
||||
|
||||
# Сохраняем связанные параметры
|
||||
if parameter_forms.is_valid():
|
||||
instances = parameter_forms.save(commit=False)
|
||||
for instance in instances:
|
||||
instance.save()
|
||||
instance.objitems.set([self.object])
|
||||
|
||||
# Сохраняем геоданные
|
||||
geo_instance = None
|
||||
if hasattr(self.object, 'geo_obj'):
|
||||
geo_instance = self.object.geo_obj
|
||||
|
||||
# Создаем или обновляем гео-объект
|
||||
if geo_instance is None:
|
||||
geo_instance = Geo(objitem=self.object)
|
||||
|
||||
# Обновляем поля из geo_form
|
||||
if geo_form.is_valid():
|
||||
geo_instance.location = geo_form.cleaned_data['location']
|
||||
geo_instance.comment = geo_form.cleaned_data['comment']
|
||||
geo_instance.is_average = geo_form.cleaned_data['is_average']
|
||||
|
||||
# Обрабатываем координаты геолокации
|
||||
geo_longitude = self.request.POST.get('geo_longitude')
|
||||
geo_latitude = self.request.POST.get('geo_latitude')
|
||||
if geo_longitude and geo_latitude:
|
||||
geo_instance.coords = Point(float(geo_longitude), float(geo_latitude))
|
||||
|
||||
# Обрабатываем координаты Кубсата
|
||||
kupsat_longitude = self.request.POST.get('kupsat_longitude')
|
||||
kupsat_latitude = self.request.POST.get('kupsat_latitude')
|
||||
if kupsat_longitude and kupsat_latitude:
|
||||
geo_instance.coords_kupsat = Point(float(kupsat_longitude), float(kupsat_latitude))
|
||||
|
||||
# Обрабатываем координаты оперативников
|
||||
valid_longitude = self.request.POST.get('valid_longitude')
|
||||
valid_latitude = self.request.POST.get('valid_latitude')
|
||||
if valid_longitude and valid_latitude:
|
||||
geo_instance.coords_valid = Point(float(valid_longitude), float(valid_latitude))
|
||||
|
||||
# Обрабатываем дату/время
|
||||
timestamp_date = self.request.POST.get('timestamp_date')
|
||||
timestamp_time = self.request.POST.get('timestamp_time')
|
||||
if timestamp_date and timestamp_time:
|
||||
naive_datetime = datetime.strptime(f"{timestamp_date} {timestamp_time}", "%Y-%m-%d %H:%M")
|
||||
geo_instance.timestamp = naive_datetime
|
||||
|
||||
geo_instance.save()
|
||||
|
||||
messages.success(self.request, 'Объект успешно сохранён!')
|
||||
return super().form_valid(form)
|
||||
|
||||
class ObjItemCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView):
|
||||
model = ObjItem
|
||||
form_class = ObjItemForm
|
||||
template_name = 'mainapp/objitem_form.html'
|
||||
success_url = reverse_lazy('home')
|
||||
|
||||
def test_func(self):
|
||||
return self.request.user.customuser.role in ['admin', 'moderator']
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
ParameterFormSet = modelformset_factory(
|
||||
Parameter,
|
||||
form=ParameterForm,
|
||||
extra=1,
|
||||
can_delete=True
|
||||
)
|
||||
|
||||
context['parameter_forms'] = ParameterFormSet(
|
||||
queryset=Parameter.objects.none(),
|
||||
prefix='parameters'
|
||||
)
|
||||
|
||||
context['geo_form'] = GeoForm(prefix='geo')
|
||||
|
||||
return context
|
||||
|
||||
def form_valid(self, form):
|
||||
context = self.get_context_data()
|
||||
parameter_forms = context['parameter_forms']
|
||||
geo_form = context['geo_form']
|
||||
|
||||
# Сохраняем основной объект
|
||||
self.object = form.save(commit=False)
|
||||
self.object.created_by = self.request.user.customuser
|
||||
self.object.updated_by = self.request.user.customuser
|
||||
self.object.save()
|
||||
|
||||
# Сохраняем связанные параметры
|
||||
if parameter_forms.is_valid():
|
||||
instances = parameter_forms.save(commit=False)
|
||||
for instance in instances:
|
||||
instance.save()
|
||||
instance.objitems.add(self.object)
|
||||
|
||||
# Создаем гео-объект
|
||||
geo_instance = Geo(objitem=self.object)
|
||||
|
||||
# Обновляем поля из geo_form
|
||||
if geo_form.is_valid():
|
||||
geo_instance.location = geo_form.cleaned_data['location']
|
||||
geo_instance.comment = geo_form.cleaned_data['comment']
|
||||
geo_instance.is_average = geo_form.cleaned_data['is_average']
|
||||
|
||||
# Обрабатываем координаты геолокации
|
||||
geo_longitude = self.request.POST.get('geo_longitude')
|
||||
geo_latitude = self.request.POST.get('geo_latitude')
|
||||
if geo_longitude and geo_latitude:
|
||||
geo_instance.coords = Point(float(geo_longitude), float(geo_latitude))
|
||||
|
||||
# Обрабатываем координаты Кубсата
|
||||
kupsat_longitude = self.request.POST.get('kupsat_longitude')
|
||||
kupsat_latitude = self.request.POST.get('kupsat_latitude')
|
||||
if kupsat_longitude and kupsat_latitude:
|
||||
geo_instance.coords_kupsat = Point(float(kupsat_longitude), float(kupsat_latitude))
|
||||
|
||||
# Обрабатываем координаты оперативников
|
||||
valid_longitude = self.request.POST.get('valid_longitude')
|
||||
valid_latitude = self.request.POST.get('valid_latitude')
|
||||
if valid_longitude and valid_latitude:
|
||||
geo_instance.coords_valid = Point(float(valid_longitude), float(valid_latitude))
|
||||
|
||||
# Обрабатываем дату/время
|
||||
timestamp_date = self.request.POST.get('timestamp_date')
|
||||
timestamp_time = self.request.POST.get('timestamp_time')
|
||||
if timestamp_date and timestamp_time:
|
||||
naive_datetime = datetime.strptime(f"{timestamp_date} {timestamp_time}", "%Y-%m-%d %H:%M")
|
||||
geo_instance.timestamp = naive_datetime
|
||||
|
||||
geo_instance.save()
|
||||
|
||||
messages.success(self.request, 'Объект успешно создан!')
|
||||
return super().form_valid(form)
|
||||
|
||||
class ObjItemDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
|
||||
model = ObjItem
|
||||
template_name = 'mainapp/objitem_confirm_delete.html'
|
||||
success_url = reverse_lazy('home')
|
||||
|
||||
def test_func(self):
|
||||
return self.request.user.customuser.role in ['admin', 'moderator']
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
messages.success(self.request, 'Объект успешно удалён!')
|
||||
return super().delete(request, *args, **kwargs)
|
||||
Reference in New Issue
Block a user