Привязка данных LyngSat
This commit is contained in:
@@ -25,7 +25,6 @@ from .models import (
|
||||
Standard,
|
||||
SigmaParMark,
|
||||
SigmaParameter,
|
||||
SourceType,
|
||||
Parameter,
|
||||
Satellite,
|
||||
Mirror,
|
||||
@@ -336,14 +335,6 @@ class ModulationAdmin(BaseAdmin):
|
||||
ordering = ("name",)
|
||||
|
||||
|
||||
@admin.register(SourceType)
|
||||
class SourceTypeAdmin(BaseAdmin):
|
||||
"""Админ-панель для модели SourceType."""
|
||||
list_display = ("name",)
|
||||
search_fields = ("name",)
|
||||
ordering = ("name",)
|
||||
|
||||
|
||||
@admin.register(Standard)
|
||||
class StandardAdmin(BaseAdmin):
|
||||
"""Админ-панель для модели Standard."""
|
||||
|
||||
@@ -161,6 +161,32 @@ class FillLyngsatDataForm(forms.Form):
|
||||
}),
|
||||
help_text="Игнорировать кеш и получить свежие данные с сайта"
|
||||
)
|
||||
|
||||
|
||||
class LinkLyngsatForm(forms.Form):
|
||||
"""Форма для привязки источников LyngSat к объектам"""
|
||||
|
||||
satellites = forms.ModelMultipleChoiceField(
|
||||
queryset=Satellite.objects.all().order_by('name'),
|
||||
label="Выберите спутники",
|
||||
widget=forms.SelectMultiple(attrs={
|
||||
'class': 'form-select',
|
||||
'size': '10'
|
||||
}),
|
||||
required=False,
|
||||
help_text="Оставьте пустым для обработки всех спутников"
|
||||
)
|
||||
|
||||
frequency_tolerance = forms.FloatField(
|
||||
label="Допуск по частоте (МГц)",
|
||||
initial=0.5,
|
||||
min_value=0,
|
||||
widget=forms.NumberInput(attrs={
|
||||
'class': 'form-control',
|
||||
'step': '0.1'
|
||||
}),
|
||||
help_text="Допустимое отклонение частоты при сравнении"
|
||||
)
|
||||
class ParameterForm(forms.ModelForm):
|
||||
"""
|
||||
Форма для создания и редактирования параметров ВЧ загрузки.
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# Generated by Django 5.2.7 on 2025-11-11 19:02
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('lyngsatapp', '0002_alter_lyngsat_last_update'),
|
||||
('mainapp', '0008_remove_sourcetype_objitem_objitem_source_type_id_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='objitem',
|
||||
name='source_type_id',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='objitem',
|
||||
name='lyngsat_source',
|
||||
field=models.ForeignKey(blank=True, help_text='Связанный источник из базы LyngSat (ТВ)', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='objitems', to='lyngsatapp.lyngsat', verbose_name='Источник LyngSat'),
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='SourceType',
|
||||
),
|
||||
]
|
||||
@@ -233,27 +233,7 @@ class Satellite(models.Model):
|
||||
ordering = ["name"]
|
||||
|
||||
|
||||
class SourceType(models.Model):
|
||||
"""
|
||||
Модель типа источника сигнала.
|
||||
Классифицирует источники по типам (наземный, морской, воздушный и т.д.).
|
||||
"""
|
||||
# Основные поля
|
||||
name = models.CharField(
|
||||
max_length=50,
|
||||
unique=True,
|
||||
verbose_name="Тип источника",
|
||||
db_index=True,
|
||||
help_text="Тип источника сигнала",
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Тип источника"
|
||||
verbose_name_plural = "Типы источников"
|
||||
ordering = ["name"]
|
||||
|
||||
class ObjItemQuerySet(models.QuerySet):
|
||||
"""Custom QuerySet для модели ObjItem с оптимизированными запросами"""
|
||||
@@ -264,7 +244,7 @@ class ObjItemQuerySet(models.QuerySet):
|
||||
"geo_obj",
|
||||
"updated_by__user",
|
||||
"created_by__user",
|
||||
"source_type_obj",
|
||||
"lyngsat_source",
|
||||
"parameter_obj",
|
||||
"parameter_obj__id_satellite",
|
||||
"parameter_obj__polarization",
|
||||
@@ -349,14 +329,14 @@ class ObjItem(models.Model):
|
||||
verbose_name="Изменен пользователем",
|
||||
help_text="Пользователь, последним изменивший запись",
|
||||
)
|
||||
source_type_id = models.ForeignKey(
|
||||
SourceType,
|
||||
lyngsat_source = models.ForeignKey(
|
||||
"lyngsatapp.LyngSat",
|
||||
on_delete=models.SET_NULL,
|
||||
related_name="objitems_sourcetype",
|
||||
related_name="objitems",
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name="Тип источника",
|
||||
help_text="Тип источника сигнала",
|
||||
verbose_name="Источник LyngSat",
|
||||
help_text="Связанный источник из базы LyngSat (ТВ)",
|
||||
)
|
||||
|
||||
# Custom manager
|
||||
|
||||
@@ -184,6 +184,27 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Link LyngSat Sources Card -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100 shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-primary bg-opacity-10 rounded-circle p-2 me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-link-45deg text-primary" viewBox="0 0 16 16">
|
||||
<path d="M4.715 6.542 3.343 7.914a3 3 0 1 0 4.243 4.243l1.828-1.829A3 3 0 0 0 8.586 5.5L8 6.086a1.002 1.002 0 0 0-.154.199 2 2 0 0 1 .861 3.337L6.88 11.45a2 2 0 1 1-2.83-2.83l.793-.792a4.018 4.018 0 0 1-.128-1.287z"/>
|
||||
<path d="M6.586 4.672A3 3 0 0 0 7.414 9.5l.775-.776a2 2 0 0 1-.896-3.346L9.12 3.55a2 2 0 1 1 2.83 2.83l-.793.792c.112.42.155.855.128 1.287l1.372-1.372a3 3 0 1 0-4.243-4.243z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Привязка источников LyngSat</h3>
|
||||
</div>
|
||||
<p class="card-text">Автоматическая привязка источников из базы LyngSat к объектам по частоте и поляризации. Объекты с привязанными источниками отображаются как "ТВ".</p>
|
||||
<a href="{% url 'mainapp:link_lyngsat' %}" class="btn btn-primary">
|
||||
Привязать источники
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
90
dbapp/mainapp/templates/mainapp/link_lyngsat.html
Normal file
90
dbapp/mainapp/templates/mainapp/link_lyngsat.html
Normal file
@@ -0,0 +1,90 @@
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Привязка источников LyngSat{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h3 class="mb-0">
|
||||
<i class="bi bi-link-45deg"></i> Привязка источников LyngSat к объектам
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- Alert messages -->
|
||||
{% include 'mainapp/components/_messages.html' %}
|
||||
|
||||
<div class="alert alert-info" role="alert">
|
||||
<i class="bi bi-info-circle"></i>
|
||||
<strong>Информация:</strong> Эта функция автоматически привязывает источники из базы LyngSat к объектам
|
||||
на основе совпадения частоты (с округлением) и поляризации. Объекты с привязанными источниками LyngSat
|
||||
будут отмечены как "ТВ" в списке объектов.
|
||||
</div>
|
||||
|
||||
<form method="post" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="{{ form.satellites.id_for_label }}" class="form-label">
|
||||
{{ form.satellites.label }}
|
||||
</label>
|
||||
{{ form.satellites }}
|
||||
{% if form.satellites.help_text %}
|
||||
<div class="form-text">{{ form.satellites.help_text }}</div>
|
||||
{% endif %}
|
||||
{% if form.satellites.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.satellites.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="{{ form.frequency_tolerance.id_for_label }}" class="form-label">
|
||||
{{ form.frequency_tolerance.label }}
|
||||
</label>
|
||||
{{ form.frequency_tolerance }}
|
||||
{% if form.frequency_tolerance.help_text %}
|
||||
<div class="form-text">{{ form.frequency_tolerance.help_text }}</div>
|
||||
{% endif %}
|
||||
{% if form.frequency_tolerance.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.frequency_tolerance.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2">
|
||||
<button type="submit" class="btn btn-primary btn-lg">
|
||||
<i class="bi bi-link-45deg"></i> Привязать источники
|
||||
</button>
|
||||
<a href="{% url 'mainapp:actions' %}" class="btn btn-secondary">
|
||||
<i class="bi bi-arrow-left"></i> Назад к действиям
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Help section -->
|
||||
<div class="card mt-4 shadow-sm">
|
||||
<div class="card-header bg-light">
|
||||
<h5 class="mb-0">
|
||||
<i class="bi bi-question-circle"></i> Как это работает?
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ol class="mb-0">
|
||||
<li>Система округляет частоту каждого объекта до целого числа</li>
|
||||
<li>Ищет источники LyngSat с той же поляризацией и близкой частотой (в пределах допуска)</li>
|
||||
<li>При нахождении совпадения создается связь между объектом и источником LyngSat</li>
|
||||
<li>Объекты с привязанными источниками отображаются как "ТВ" в списке</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -251,6 +251,12 @@
|
||||
onchange="toggleColumn(this)"> Стандарт
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label class="dropdown-item">
|
||||
<input type="checkbox" class="column-toggle" data-column="24" checked
|
||||
onchange="toggleColumn(this)"> Тип источника
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -463,6 +469,7 @@
|
||||
{% include 'mainapp/components/_table_header.html' with label="Комментарий" field="" sortable=False %}
|
||||
{% include 'mainapp/components/_table_header.html' with label="Усреднённое" field="" sortable=False %}
|
||||
{% include 'mainapp/components/_table_header.html' with label="Стандарт" field="standard" sort=sort %}
|
||||
{% include 'mainapp/components/_table_header.html' with label="Тип источника" field="" sortable=False %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -495,10 +502,19 @@
|
||||
<td>{{ item.comment }}</td>
|
||||
<td>{{ item.is_average }}</td>
|
||||
<td>{{ item.standard }}</td>
|
||||
<td>
|
||||
{% if item.obj.lyngsat_source %}
|
||||
<a href="#" class="text-primary text-decoration-none" onclick="showLyngsatModal({{ item.obj.lyngsat_source.id }}); return false;">
|
||||
<i class="bi bi-tv"></i> ТВ
|
||||
</a>
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="22" class="text-center py-4">
|
||||
<td colspan="25" class="text-center py-4">
|
||||
{% if selected_satellite_id %}
|
||||
Нет данных для выбранных фильтров
|
||||
{% else %}
|
||||
@@ -1165,4 +1181,160 @@
|
||||
|
||||
<!-- Include the selected items offcanvas component -->
|
||||
{% include 'mainapp/components/_selected_items_offcanvas.html' %}
|
||||
|
||||
<!-- LyngSat Data Modal -->
|
||||
<div class="modal fade" id="lyngsatModal" tabindex="-1" aria-labelledby="lyngsatModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-primary text-white">
|
||||
<h5 class="modal-title" id="lyngsatModalLabel">
|
||||
<i class="bi bi-tv"></i> Данные источника LyngSat
|
||||
</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Закрыть"></button>
|
||||
</div>
|
||||
<div class="modal-body" id="lyngsatModalBody">
|
||||
<div class="text-center py-4">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="visually-hidden">Загрузка...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function showLyngsatModal(lyngsatId) {
|
||||
// Показываем модальное окно
|
||||
const modal = new bootstrap.Modal(document.getElementById('lyngsatModal'));
|
||||
modal.show();
|
||||
|
||||
// Показываем индикатор загрузки
|
||||
const modalBody = document.getElementById('lyngsatModalBody');
|
||||
modalBody.innerHTML = `
|
||||
<div class="text-center py-4">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="visually-hidden">Загрузка...</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Загружаем данные
|
||||
fetch(`/api/lyngsat/${lyngsatId}/`)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Ошибка загрузки данных');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
// Формируем HTML с данными
|
||||
let html = `
|
||||
<div class="container-fluid">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<div class="card h-100">
|
||||
<div class="card-header bg-light">
|
||||
<strong><i class="bi bi-info-circle"></i> Основная информация</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table table-sm table-borderless mb-0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-muted" style="width: 40%;">Спутник:</td>
|
||||
<td><strong>${data.satellite}</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-muted">Частота:</td>
|
||||
<td><strong>${data.frequency} МГц</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-muted">Поляризация:</td>
|
||||
<td><span class="badge bg-info">${data.polarization}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-muted">Канал:</td>
|
||||
<td>${data.channel_info}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card h-100">
|
||||
<div class="card-header bg-light">
|
||||
<strong><i class="bi bi-gear"></i> Технические параметры</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table table-sm table-borderless mb-0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-muted" style="width: 40%;">Модуляция:</td>
|
||||
<td><span class="badge bg-secondary">${data.modulation}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-muted">Стандарт:</td>
|
||||
<td><span class="badge bg-secondary">${data.standard}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-muted">Сим. скорость:</td>
|
||||
<td><strong>${data.sym_velocity} БОД</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-muted">FEC:</td>
|
||||
<td>${data.fec}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header bg-light">
|
||||
<strong><i class="bi bi-clock-history"></i> Дополнительная информация</strong>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<p class="mb-2">
|
||||
<span class="text-muted">Последнее обновление:</span><br>
|
||||
<strong>${data.last_update}</strong>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
${data.url ? `
|
||||
<p class="mb-2">
|
||||
<span class="text-muted">Ссылка на источник:</span><br>
|
||||
<a href="${data.url}" target="_blank" class="btn btn-sm btn-outline-primary">
|
||||
<i class="bi bi-link-45deg"></i> Открыть на LyngSat
|
||||
</a>
|
||||
</p>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
modalBody.innerHTML = html;
|
||||
})
|
||||
.catch(error => {
|
||||
modalBody.innerHTML = `
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<i class="bi bi-exclamation-triangle"></i> ${error.message}
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -20,6 +20,8 @@ urlpatterns = [
|
||||
path('cluster/', views.ClusterTestView.as_view(), name='cluster'),
|
||||
path('vch-upload/', views.UploadVchLoadView.as_view(), name='vch_load'),
|
||||
path('vch-link/', views.LinkVchSigmaView.as_view(), name='link_vch_sigma'),
|
||||
path('link-lyngsat/', views.LinkLyngsatSourcesView.as_view(), name='link_lyngsat'),
|
||||
path('api/lyngsat/<int:lyngsat_id>/', views.LyngsatDataAPIView.as_view(), name='lyngsat_data_api'),
|
||||
path('kubsat-excel/', views.ProcessKubsatView.as_view(), name='kubsat_excel'),
|
||||
path('object/create/', views.ObjItemCreateView.as_view(), name='objitem_create'),
|
||||
path('object/<int:pk>/edit/', views.ObjItemUpdateView.as_view(), name='objitem_update'),
|
||||
|
||||
@@ -3,6 +3,7 @@ from collections import defaultdict
|
||||
from io import BytesIO
|
||||
|
||||
# Django imports
|
||||
from django.utils import timezone
|
||||
from django.contrib import messages
|
||||
from django.contrib.admin.views.decorators import staff_member_required
|
||||
from django.contrib.auth import logout
|
||||
@@ -38,6 +39,7 @@ from .forms import (
|
||||
UploadVchLoad,
|
||||
VchLinkForm,
|
||||
FillLyngsatDataForm,
|
||||
LinkLyngsatForm,
|
||||
)
|
||||
from .mixins import CoordinateProcessingMixin, FormMessageMixin, RoleRequiredMixin
|
||||
from .models import Geo, Modulation, ObjItem, Polarization, Satellite
|
||||
@@ -375,6 +377,108 @@ class LinkVchSigmaView(LoginRequiredMixin, FormView):
|
||||
return self.render_to_response(self.get_context_data(form=form))
|
||||
|
||||
|
||||
class LinkLyngsatSourcesView(LoginRequiredMixin, FormMessageMixin, FormView):
|
||||
"""Представление для привязки источников LyngSat к объектам"""
|
||||
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:
|
||||
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
|
||||
|
||||
# Округляем частоту объекта
|
||||
if param.frequency:
|
||||
rounded_freq = round(param.frequency, 0) # Округление до целого
|
||||
|
||||
# Ищем подходящий источник LyngSat
|
||||
# Сравниваем по округленной частоте и поляризации
|
||||
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():
|
||||
# Берем первый подходящий источник
|
||||
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 LyngsatDataAPIView(LoginRequiredMixin, View):
|
||||
"""API для получения данных LyngSat источника"""
|
||||
|
||||
def get(self, request, lyngsat_id):
|
||||
from lyngsatapp.models import LyngSat
|
||||
|
||||
try:
|
||||
lyngsat = LyngSat.objects.select_related(
|
||||
'id_satellite',
|
||||
'polarization',
|
||||
'modulation',
|
||||
'standard'
|
||||
).get(id=lyngsat_id)
|
||||
|
||||
# Форматируем дату с учетом локального времени
|
||||
last_update_str = '-'
|
||||
if lyngsat.last_update:
|
||||
local_time = timezone.localtime(lyngsat.last_update)
|
||||
last_update_str = local_time.strftime("%d.%m.%Y")
|
||||
|
||||
data = {
|
||||
'id': lyngsat.id,
|
||||
'satellite': lyngsat.id_satellite.name if lyngsat.id_satellite else '-',
|
||||
'frequency': f"{lyngsat.frequency:.3f}" if lyngsat.frequency else '-',
|
||||
'polarization': lyngsat.polarization.name if lyngsat.polarization else '-',
|
||||
'modulation': lyngsat.modulation.name if lyngsat.modulation else '-',
|
||||
'standard': lyngsat.standard.name if lyngsat.standard else '-',
|
||||
'sym_velocity': f"{lyngsat.sym_velocity:.0f}" if lyngsat.sym_velocity else '-',
|
||||
'fec': lyngsat.fec or '-',
|
||||
'channel_info': lyngsat.channel_info or '-',
|
||||
'last_update': last_update_str,
|
||||
'url': lyngsat.url or None,
|
||||
}
|
||||
|
||||
return JsonResponse(data)
|
||||
except LyngSat.DoesNotExist:
|
||||
return JsonResponse({'error': 'Источник LyngSat не найден'}, status=404)
|
||||
except Exception as e:
|
||||
return JsonResponse({'error': str(e)}, status=500)
|
||||
|
||||
|
||||
class ProcessKubsatView(LoginRequiredMixin, FormMessageMixin, FormView):
|
||||
template_name = "mainapp/process_kubsat.html"
|
||||
form_class = NewEventForm
|
||||
@@ -474,6 +578,7 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
"geo_obj",
|
||||
"updated_by__user",
|
||||
"created_by__user",
|
||||
"lyngsat_source",
|
||||
"parameter_obj",
|
||||
"parameter_obj__id_satellite",
|
||||
"parameter_obj__polarization",
|
||||
@@ -487,6 +592,7 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
"geo_obj",
|
||||
"updated_by__user",
|
||||
"created_by__user",
|
||||
"lyngsat_source",
|
||||
"parameter_obj",
|
||||
"parameter_obj__id_satellite",
|
||||
"parameter_obj__polarization",
|
||||
@@ -763,6 +869,9 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
comment = obj.geo_obj.comment or "-"
|
||||
is_average = "Да" if obj.geo_obj.is_average else "Нет" if obj.geo_obj.is_average is not None else "-"
|
||||
|
||||
# Check if LyngSat source is linked
|
||||
source_type = "ТВ" if obj.lyngsat_source else "-"
|
||||
|
||||
processed_objects.append(
|
||||
{
|
||||
"id": obj.id,
|
||||
@@ -785,6 +894,7 @@ class ObjItemListView(LoginRequiredMixin, View):
|
||||
"updated_by": obj.updated_by if obj.updated_by else "-",
|
||||
"comment": comment,
|
||||
"is_average": is_average,
|
||||
"source_type": source_type,
|
||||
"standard": standard_name,
|
||||
"obj": obj,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user