Добавил форму для загрузки данных с LyngSat
This commit is contained in:
@@ -107,6 +107,40 @@ class NewEventForm(forms.Form):
|
||||
'accept': '.xlsx,.xls'
|
||||
})
|
||||
)
|
||||
|
||||
|
||||
class FillLyngsatDataForm(forms.Form):
|
||||
"""Форма для заполнения данных из Lyngsat"""
|
||||
|
||||
REGION_CHOICES = [
|
||||
('europe', 'Европа'),
|
||||
('asia', 'Азия'),
|
||||
('america', 'Америка'),
|
||||
('atlantic', 'Атлантика'),
|
||||
]
|
||||
|
||||
satellites = forms.ModelMultipleChoiceField(
|
||||
queryset=Satellite.objects.all().order_by('name'),
|
||||
label="Выберите спутники",
|
||||
widget=forms.SelectMultiple(attrs={
|
||||
'class': 'form-select',
|
||||
'size': '10'
|
||||
}),
|
||||
required=True,
|
||||
help_text="Удерживайте Ctrl (Cmd на Mac) для выбора нескольких спутников"
|
||||
)
|
||||
|
||||
regions = forms.MultipleChoiceField(
|
||||
choices=REGION_CHOICES,
|
||||
label="Выберите регионы",
|
||||
widget=forms.SelectMultiple(attrs={
|
||||
'class': 'form-select',
|
||||
'size': '4'
|
||||
}),
|
||||
required=True,
|
||||
initial=['europe', 'asia', 'america', 'atlantic'],
|
||||
help_text="Удерживайте Ctrl (Cmd на Mac) для выбора нескольких регионов"
|
||||
)
|
||||
class ParameterForm(forms.ModelForm):
|
||||
"""
|
||||
Форма для создания и редактирования параметров ВЧ загрузки.
|
||||
|
||||
@@ -124,23 +124,23 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Map Views Card -->
|
||||
<!-- Lyngsat Data Fill 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-secondary 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-map text-secondary" viewBox="0 0 16 16">
|
||||
<path d="M15.817.113A.5.5 0 0 1 16 .5v14a.5.5 0 0 1-.402.49l-5 1a.502.502 0 0 1-.196 0L5.5 15.01l-4.902.98A.5.5 0 0 1 0 15.5v-14a.5.5 0 0 1 .402-.49l5-1a.5.5 0 0 1 .196 0L10.5.99l4.902-.98a.5.5 0 0 1 .415.103M10 1.91l-4-.8v12.98l4 .8zM1.61 2.22l4.39.88v10.88l-4.39-.88zm9.18 10.88 4-.8V2.34l-4 .8z"/>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-cloud-download text-secondary" viewBox="0 0 16 16">
|
||||
<path d="M4.406 1.342A5.53 5.53 0 0 1 8 0c2.69 0 4.923 2 5.166 4.579C14.758 4.804 16 6.137 16 7.773 16 9.569 14.502 11 12.687 11H10a.5.5 0 0 1 0-1h2.688C13.979 10 15 8.988 15 7.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 2.825 10.328 1 8 1a4.53 4.53 0 0 0-2.941 1.1c-.757.652-1.153 1.438-1.153 2.055v.448l-.445.049C2.064 4.805 1 5.952 1 7.318 1 8.785 2.23 10 3.781 10H6a.5.5 0 0 1 0 1H3.781C1.708 11 0 9.366 0 7.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383"/>
|
||||
<path d="M7.646 15.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 14.293V5.5a.5.5 0 0 0-1 0v8.793l-2.146-2.147a.5.5 0 0 0-.708.708z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="card-title mb-0">Карты</h3>
|
||||
</div>
|
||||
<p class="card-text">Просматривайте данные на 2D и 3D картах для визуализации геолокации спутников.</p>
|
||||
<div class="mt-2">
|
||||
<a href="{% url 'mapsapp:2dmap' %}" class="btn btn-secondary me-2">2D Карта</a>
|
||||
<a href="{% url 'mapsapp:3dmap' %}" class="btn btn-outline-secondary">3D Карта</a>
|
||||
<h3 class="card-title mb-0">Заполнение данных Lyngsat</h3>
|
||||
</div>
|
||||
<p class="card-text">Загрузите данные о транспондерах спутников с сайта Lyngsat. Выберите спутники и регионы для парсинга данных.</p>
|
||||
<a href="{% url 'mainapp:fill_lyngsat_data' %}" class="btn btn-secondary">
|
||||
Заполнить данные Lyngsat
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
118
dbapp/mainapp/templates/mainapp/fill_lyngsat_data.html
Normal file
118
dbapp/mainapp/templates/mainapp/fill_lyngsat_data.html
Normal file
@@ -0,0 +1,118 @@
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Заполнение данных Lyngsat{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h3 class="mb-0">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-cloud-download me-2" viewBox="0 0 16 16">
|
||||
<path d="M4.406 1.342A5.53 5.53 0 0 1 8 0c2.69 0 4.923 2 5.166 4.579C14.758 4.804 16 6.137 16 7.773 16 9.569 14.502 11 12.687 11H10a.5.5 0 0 1 0-1h2.688C13.979 10 15 8.988 15 7.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 2.825 10.328 1 8 1a4.53 4.53 0 0 0-2.941 1.1c-.757.652-1.153 1.438-1.153 2.055v.448l-.445.049C2.064 4.805 1 5.952 1 7.318 1 8.785 2.23 10 3.781 10H6a.5.5 0 0 1 0 1H3.781C1.708 11 0 9.366 0 7.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383"/>
|
||||
<path d="M7.646 15.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 14.293V5.5a.5.5 0 0 0-1 0v8.793l-2.146-2.147a.5.5 0 0 0-.708.708z"/>
|
||||
</svg>
|
||||
Заполнение данных из Lyngsat
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- Alert messages -->
|
||||
{% include 'mainapp/components/_messages.html' %}
|
||||
|
||||
<div class="alert alert-info" role="alert">
|
||||
<strong>Внимание!</strong> Процесс заполнения данных может занять продолжительное время,
|
||||
так как выполняются запросы к внешнему сайту Lyngsat. Пожалуйста, дождитесь завершения операции.
|
||||
</div>
|
||||
|
||||
<form method="post" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
|
||||
<!-- Satellites Selection -->
|
||||
<div class="mb-4">
|
||||
<label for="{{ form.satellites.id_for_label }}" class="form-label fw-bold">
|
||||
{{ 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>
|
||||
|
||||
<!-- Regions Selection -->
|
||||
<div class="mb-4">
|
||||
<label for="{{ form.regions.id_for_label }}" class="form-label fw-bold">
|
||||
{{ form.regions.label }}
|
||||
</label>
|
||||
{{ form.regions }}
|
||||
{% if form.regions.help_text %}
|
||||
<div class="form-text">{{ form.regions.help_text }}</div>
|
||||
{% endif %}
|
||||
{% if form.regions.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.regions.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Buttons -->
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-between">
|
||||
<a href="{% url 'mainapp:actions' %}" class="btn btn-secondary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left me-1" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8"/>
|
||||
</svg>
|
||||
Назад
|
||||
</a>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-download me-1" viewBox="0 0 16 16">
|
||||
<path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5"/>
|
||||
<path d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708z"/>
|
||||
</svg>
|
||||
Заполнить данные
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info Card -->
|
||||
<div class="card mt-4 shadow-sm">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Информация</h5>
|
||||
<p class="card-text">
|
||||
Эта форма позволяет загрузить данные о транспондерах спутников с сайта Lyngsat.
|
||||
Выберите один или несколько спутников и регионы для парсинга данных.
|
||||
</p>
|
||||
<ul>
|
||||
<li>Данные включают частоты, поляризацию, модуляцию, стандарты и другие параметры</li>
|
||||
<li>Процесс может занять несколько минут в зависимости от количества выбранных спутников</li>
|
||||
<li>Существующие записи будут обновлены, новые - созданы</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Form validation
|
||||
(function() {
|
||||
'use strict';
|
||||
var forms = document.querySelectorAll('.needs-validation');
|
||||
Array.prototype.slice.call(forms).forEach(function(form) {
|
||||
form.addEventListener('submit', function(event) {
|
||||
if (!form.checkValidity()) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
form.classList.add('was-validated');
|
||||
}, false);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
241
dbapp/mainapp/templates/mainapp/lyngsat_task_status.html
Normal file
241
dbapp/mainapp/templates/mainapp/lyngsat_task_status.html
Normal file
@@ -0,0 +1,241 @@
|
||||
{% extends 'mainapp/base.html' %}
|
||||
|
||||
{% block title %}Статус задачи Lyngsat{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h3 class="mb-0">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-hourglass-split me-2" viewBox="0 0 16 16">
|
||||
<path d="M2.5 15a.5.5 0 1 1 0-1h1v-1a4.5 4.5 0 0 1 2.557-4.06c.29-.139.443-.377.443-.59v-.7c0-.213-.154-.451-.443-.59A4.5 4.5 0 0 1 3.5 3V2h-1a.5.5 0 0 1 0-1h11a.5.5 0 0 1 0 1h-1v1a4.5 4.5 0 0 1-2.557 4.06c-.29.139-.443.377-.443.59v.7c0 .213.154.451.443.59A4.5 4.5 0 0 1 12.5 13v1h1a.5.5 0 0 1 0 1zm2-13v1c0 .537.12 1.045.337 1.5h6.326c.216-.455.337-.963.337-1.5V2zm3 6.35c0 .701-.478 1.236-1.011 1.492A3.5 3.5 0 0 0 4.5 13s.866-1.299 3-1.48zm1 0v3.17c2.134.181 3 1.48 3 1.48a3.5 3.5 0 0 0-1.989-3.158C8.978 9.586 8.5 9.052 8.5 8.351z"/>
|
||||
</svg>
|
||||
Статус задачи заполнения данных Lyngsat
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if task_id %}
|
||||
<div class="mb-3">
|
||||
<strong>ID задачи:</strong> <code id="task-id">{{ task_id }}</code>
|
||||
</div>
|
||||
|
||||
<!-- Progress Bar -->
|
||||
<div class="mb-4">
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<span id="status-text">Загрузка статуса...</span>
|
||||
<span id="progress-percent">0%</span>
|
||||
</div>
|
||||
<div class="progress" style="height: 25px;">
|
||||
<div id="progress-bar" class="progress-bar progress-bar-striped progress-bar-animated"
|
||||
role="progressbar" style="width: 0%;"
|
||||
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
|
||||
<span id="progress-text">0%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Task State -->
|
||||
<div id="task-state-container" class="alert alert-info" role="alert">
|
||||
<strong>Состояние:</strong> <span id="task-state">Проверка...</span>
|
||||
</div>
|
||||
|
||||
<!-- Results Container (hidden by default) -->
|
||||
<div id="results-container" class="d-none">
|
||||
<h5 class="mt-4">Результаты обработки</h5>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h6 class="card-subtitle mb-2 text-muted">Обработано спутников</h6>
|
||||
<h3 class="card-title" id="result-satellites">-</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h6 class="card-subtitle mb-2 text-muted">Обработано источников</h6>
|
||||
<h3 class="card-title" id="result-sources">-</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-3 border-success">
|
||||
<div class="card-body">
|
||||
<h6 class="card-subtitle mb-2 text-success">Создано записей</h6>
|
||||
<h3 class="card-title text-success" id="result-created">-</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-3 border-info">
|
||||
<div class="card-body">
|
||||
<h6 class="card-subtitle mb-2 text-info">Обновлено записей</h6>
|
||||
<h3 class="card-title text-info" id="result-updated">-</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Errors -->
|
||||
<div id="errors-container" class="d-none">
|
||||
<h6 class="text-danger">Ошибки при обработке:</h6>
|
||||
<div class="alert alert-warning">
|
||||
<ul id="errors-list" class="mb-0"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Error Container (hidden by default) -->
|
||||
<div id="error-container" class="alert alert-danger d-none" role="alert">
|
||||
<strong>Ошибка:</strong> <span id="error-text"></span>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-between mt-4">
|
||||
<a href="{% url 'mainapp:fill_lyngsat_data' %}" class="btn btn-secondary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left me-1" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8"/>
|
||||
</svg>
|
||||
Назад к форме
|
||||
</a>
|
||||
<a href="{% url 'mainapp:actions' %}" class="btn btn-outline-primary" id="actions-btn">
|
||||
Перейти к действиям
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-warning" role="alert">
|
||||
ID задачи не указан. Пожалуйста, запустите задачу через форму заполнения данных.
|
||||
</div>
|
||||
<a href="{% url 'mainapp:fill_lyngsat_data' %}" class="btn btn-primary">
|
||||
Перейти к форме
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if task_id %}
|
||||
<script>
|
||||
let taskId = '{{ task_id }}';
|
||||
let pollInterval;
|
||||
let isCompleted = false;
|
||||
|
||||
function updateProgress(data) {
|
||||
const statusText = document.getElementById('status-text');
|
||||
const progressBar = document.getElementById('progress-bar');
|
||||
const progressText = document.getElementById('progress-text');
|
||||
const progressPercent = document.getElementById('progress-percent');
|
||||
const taskState = document.getElementById('task-state');
|
||||
const taskStateContainer = document.getElementById('task-state-container');
|
||||
|
||||
// Update state
|
||||
taskState.textContent = data.state;
|
||||
|
||||
if (data.state === 'PENDING') {
|
||||
statusText.textContent = 'Задача в очереди...';
|
||||
taskStateContainer.className = 'alert alert-info';
|
||||
} else if (data.state === 'PROGRESS') {
|
||||
const percent = data.percent || 0;
|
||||
statusText.textContent = data.status || 'Обработка...';
|
||||
progressBar.style.width = percent + '%';
|
||||
progressBar.setAttribute('aria-valuenow', percent);
|
||||
progressText.textContent = percent + '%';
|
||||
progressPercent.textContent = percent + '%';
|
||||
taskStateContainer.className = 'alert alert-info';
|
||||
} else if (data.state === 'SUCCESS') {
|
||||
statusText.textContent = 'Задача завершена успешно!';
|
||||
progressBar.style.width = '100%';
|
||||
progressBar.setAttribute('aria-valuenow', 100);
|
||||
progressText.textContent = '100%';
|
||||
progressPercent.textContent = '100%';
|
||||
progressBar.classList.remove('progress-bar-animated');
|
||||
progressBar.classList.add('bg-success');
|
||||
taskStateContainer.className = 'alert alert-success';
|
||||
|
||||
// Show results
|
||||
if (data.result) {
|
||||
showResults(data.result);
|
||||
}
|
||||
|
||||
isCompleted = true;
|
||||
clearInterval(pollInterval);
|
||||
} else if (data.state === 'FAILURE') {
|
||||
statusText.textContent = 'Ошибка при выполнении задачи';
|
||||
progressBar.classList.remove('progress-bar-animated');
|
||||
progressBar.classList.add('bg-danger');
|
||||
taskStateContainer.className = 'alert alert-danger';
|
||||
|
||||
// Show error
|
||||
const errorContainer = document.getElementById('error-container');
|
||||
const errorText = document.getElementById('error-text');
|
||||
errorText.textContent = data.error || 'Неизвестная ошибка';
|
||||
errorContainer.classList.remove('d-none');
|
||||
|
||||
isCompleted = true;
|
||||
clearInterval(pollInterval);
|
||||
}
|
||||
}
|
||||
|
||||
function showResults(result) {
|
||||
const resultsContainer = document.getElementById('results-container');
|
||||
resultsContainer.classList.remove('d-none');
|
||||
|
||||
document.getElementById('result-satellites').textContent = result.total_satellites || 0;
|
||||
document.getElementById('result-sources').textContent = result.total_sources || 0;
|
||||
document.getElementById('result-created').textContent = result.created || 0;
|
||||
document.getElementById('result-updated').textContent = result.updated || 0;
|
||||
|
||||
// Show errors if any
|
||||
if (result.errors && result.errors.length > 0) {
|
||||
const errorsContainer = document.getElementById('errors-container');
|
||||
const errorsList = document.getElementById('errors-list');
|
||||
errorsContainer.classList.remove('d-none');
|
||||
|
||||
errorsList.innerHTML = '';
|
||||
result.errors.slice(0, 10).forEach(error => {
|
||||
const li = document.createElement('li');
|
||||
li.textContent = error;
|
||||
errorsList.appendChild(li);
|
||||
});
|
||||
|
||||
if (result.errors.length > 10) {
|
||||
const li = document.createElement('li');
|
||||
li.textContent = `И еще ${result.errors.length - 10} ошибок...`;
|
||||
li.className = 'text-muted';
|
||||
errorsList.appendChild(li);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkTaskStatus() {
|
||||
fetch(`/api/lyngsat-task-status/${taskId}/`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
updateProgress(data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error checking task status:', error);
|
||||
});
|
||||
}
|
||||
|
||||
// Start polling
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
checkTaskStatus();
|
||||
pollInterval = setInterval(checkTaskStatus, 2000); // Poll every 2 seconds
|
||||
|
||||
// Stop polling after 30 minutes
|
||||
setTimeout(() => {
|
||||
if (!isCompleted) {
|
||||
clearInterval(pollInterval);
|
||||
document.getElementById('status-text').textContent = 'Превышено время ожидания. Обновите страницу для проверки статуса.';
|
||||
}
|
||||
}, 30 * 60 * 1000);
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -25,4 +25,8 @@ urlpatterns = [
|
||||
path('object/<int:pk>/edit/', views.ObjItemUpdateView.as_view(), name='objitem_update'),
|
||||
path('object/<int:pk>/', views.ObjItemDetailView.as_view(), name='objitem_detail'),
|
||||
path('object/<int:pk>/delete/', views.ObjItemDeleteView.as_view(), name='objitem_delete'),
|
||||
path('fill-lyngsat-data/', views.FillLyngsatDataView.as_view(), name='fill_lyngsat_data'),
|
||||
path('lyngsat-task-status/', views.LyngsatTaskStatusView.as_view(), name='lyngsat_task_status'),
|
||||
path('lyngsat-task-status/<str:task_id>/', views.LyngsatTaskStatusView.as_view(), name='lyngsat_task_status'),
|
||||
path('api/lyngsat-task-status/<str:task_id>/', views.LyngsatTaskStatusAPIView.as_view(), name='lyngsat_task_status_api'),
|
||||
]
|
||||
@@ -37,6 +37,7 @@ from .forms import (
|
||||
UploadFileForm,
|
||||
UploadVchLoad,
|
||||
VchLinkForm,
|
||||
FillLyngsatDataForm,
|
||||
)
|
||||
from .mixins import CoordinateProcessingMixin, FormMessageMixin, RoleRequiredMixin
|
||||
from .models import Geo, Modulation, ObjItem, Polarization, Satellite
|
||||
@@ -1029,3 +1030,97 @@ class ObjItemDetailView(LoginRequiredMixin, View):
|
||||
}
|
||||
|
||||
return render(request, "mainapp/objitem_detail.html", context)
|
||||
|
||||
|
||||
class FillLyngsatDataView(LoginRequiredMixin, FormMessageMixin, FormView):
|
||||
"""
|
||||
Представление для заполнения данных из Lyngsat.
|
||||
|
||||
Позволяет выбрать спутники и регионы для парсинга данных с сайта Lyngsat.
|
||||
Запускает асинхронную задачу Celery для обработки.
|
||||
"""
|
||||
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"]
|
||||
|
||||
# Получаем названия спутников
|
||||
target_sats = [sat.name for sat in satellites]
|
||||
|
||||
try:
|
||||
from lyngsatapp.tasks import fill_lyngsat_data_task
|
||||
|
||||
# Запускаем асинхронную задачу
|
||||
task = fill_lyngsat_data_task.delay(target_sats, regions)
|
||||
|
||||
messages.success(
|
||||
self.request,
|
||||
f"Задача запущена! ID задачи: {task.id}. "
|
||||
"Вы будете перенаправлены на страницу отслеживания прогресса."
|
||||
)
|
||||
|
||||
# Перенаправляем на страницу статуса задачи
|
||||
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):
|
||||
"""
|
||||
Представление для отслеживания статуса задачи заполнения данных Lyngsat.
|
||||
"""
|
||||
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 LyngsatTaskStatusAPIView(LoginRequiredMixin, View):
|
||||
"""
|
||||
API для получения статуса задачи Celery.
|
||||
"""
|
||||
def get(self, request, task_id):
|
||||
from celery.result import AsyncResult
|
||||
from django.core.cache import cache
|
||||
|
||||
task = AsyncResult(task_id)
|
||||
|
||||
response_data = {
|
||||
'task_id': task_id,
|
||||
'state': task.state,
|
||||
'result': None,
|
||||
'error': None
|
||||
}
|
||||
|
||||
if task.state == 'PENDING':
|
||||
response_data['status'] = 'Задача в очереди...'
|
||||
elif task.state == 'PROGRESS':
|
||||
response_data['status'] = task.info.get('status', '')
|
||||
response_data['current'] = task.info.get('current', 0)
|
||||
response_data['total'] = task.info.get('total', 1)
|
||||
response_data['percent'] = int((task.info.get('current', 0) / task.info.get('total', 1)) * 100)
|
||||
elif task.state == 'SUCCESS':
|
||||
# Получаем результат из кеша
|
||||
result = cache.get(f'lyngsat_task_{task_id}')
|
||||
if result:
|
||||
response_data['result'] = result
|
||||
response_data['status'] = 'Задача завершена успешно'
|
||||
else:
|
||||
response_data['result'] = task.result
|
||||
response_data['status'] = 'Задача завершена'
|
||||
elif task.state == 'FAILURE':
|
||||
response_data['status'] = 'Ошибка при выполнении задачи'
|
||||
response_data['error'] = str(task.info)
|
||||
else:
|
||||
response_data['status'] = task.state
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
Reference in New Issue
Block a user