Подправил маркеры на карте

This commit is contained in:
2025-12-03 11:47:41 +03:00
parent d7d85ac834
commit 51eb5f3732
7 changed files with 358 additions and 243 deletions

View File

@@ -120,6 +120,32 @@
.moving-marker { .moving-marker {
transition: transform 0.1s linear; transition: transform 0.1s linear;
} }
.marker-size-control {
position: fixed;
bottom: 10px;
right: 10px;
z-index: 999;
background: white;
padding: 10px 12px;
border-radius: 4px;
box-shadow: 0 1px 5px rgba(0,0,0,0.3);
font-size: 11px;
}
.marker-size-control label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.marker-size-control input[type="range"] {
width: 120px;
cursor: pointer;
}
.marker-size-control .size-value {
display: inline-block;
margin-left: 5px;
font-weight: bold;
color: #007bff;
}
</style> </style>
{% endblock %} {% endblock %}
@@ -133,6 +159,12 @@
<div id="map"></div> <div id="map"></div>
<div class="marker-size-control">
<label>Размер маркеров:</label>
<input type="range" id="markerSizeSlider" min="0.5" max="2" step="0.1" value="1">
<span class="size-value" id="sizeValue">1.0x</span>
</div>
<div class="playback-control" id="playbackControl" style="display: none;"> <div class="playback-control" id="playbackControl" style="display: none;">
<button id="playBtn" title="Воспроизвести"></button> <button id="playBtn" title="Воспроизвести"></button>
<button id="pauseBtn" title="Пауза" disabled></button> <button id="pauseBtn" title="Пауза" disabled></button>
@@ -195,7 +227,7 @@ let currentMarkers = {};
let trailPolylines = {}; let trailPolylines = {};
let staticMarkers = {}; let staticMarkers = {};
// Color mapping // Color mapping - расширенная палитра
const colorMap = { const colorMap = {
'red': '#dc3545', 'red': '#dc3545',
'blue': '#007bff', 'blue': '#007bff',
@@ -204,41 +236,85 @@ const colorMap = {
'orange': '#fd7e14', 'orange': '#fd7e14',
'cyan': '#17a2b8', 'cyan': '#17a2b8',
'magenta': '#e83e8c', 'magenta': '#e83e8c',
'yellow': '#ffc107', 'pink': '#ff69b4',
'lime': '#32cd32', 'teal': '#20c997',
'pink': '#ff69b4' 'indigo': '#6610f2',
'brown': '#8b4513',
'navy': '#000080',
'maroon': '#800000',
'olive': '#808000',
'coral': '#ff7f50',
'turquoise': '#40e0d0'
}; };
// Create marker icon using leaflet-markers library for static markers // Shape mapping - разные формы маркеров
function createStaticMarkerIcon(type) { const shapeMap = {
let markerColor = 'grey'; 'circle': (color, size) => {
const adjustedSize = Math.round(size * 0.85); // Уменьшаем на 15%
return `<div style="background: ${color}; width: ${adjustedSize}px; height: ${adjustedSize}px; border-radius: 50%; border: 1px solid black; box-sizing: border-box;"></div>`;
},
'square': (color, size) => {
const adjustedSize = Math.round(size * 0.85); // Уменьшаем на 15%
return `<div style="background: ${color}; width: ${adjustedSize}px; height: ${adjustedSize}px; border: 1px solid black; box-sizing: border-box;"></div>`;
},
'triangle': (color, size) => {
const adjustedSize = Math.round(size * 0.8); // Уменьшаем на 20%
return `<svg width="${adjustedSize}" height="${adjustedSize}" viewBox="0 0 100 100"><polygon points="50,10 90,90 10,90" fill="${color}" stroke="black" stroke-width="2"/></svg>`;
},
'star': (color, size) => `<svg width="${size}" height="${size}" viewBox="0 0 24 24"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" fill="${color}" stroke="black" stroke-width="0.8"/></svg>`,
'pentagon': (color, size) => `<svg width="${size}" height="${size}" viewBox="0 0 24 24"><path d="M12 2l7.5 5.5-2.9 9H7.4l-2.9-9z" fill="${color}" stroke="black" stroke-width="0.8"/></svg>`,
'hexagon': (color, size) => `<svg width="${size}" height="${size}" viewBox="0 0 24 24"><path d="M12 2l6 4v8l-6 4-6-4V6z" fill="${color}" stroke="black" stroke-width="0.8"/></svg>`,
'diamond': (color, size) => {
const adjustedSize = Math.round(size * 0.85); // Уменьшаем на 15%
return `<div style="background: ${color}; width: ${adjustedSize}px; height: ${adjustedSize}px; transform: rotate(45deg); border: 1px solid black; box-sizing: border-box;"></div>`;
},
'cross': (color, size) => `<svg width="${size}" height="${size}" viewBox="0 0 24 24"><path d="M9 2h6v7h7v6h-7v7H9v-7H2V9h7V2z" fill="${color}" stroke="black" stroke-width="0.8"/></svg>`
};
// Available shapes for assignment
const availableShapes = ['circle', 'square', 'triangle', 'star', 'pentagon', 'hexagon', 'diamond', 'cross'];
// Global marker size multiplier
let markerSizeMultiplier = 1.0;
// Create static marker icon (start/intermediate/end points)
function createStaticMarkerIcon(type, color, shape) {
const hexColor = colorMap[color] || color;
let baseSize = 12; // Уменьшенный базовый размер
if (type === 'start') { if (type === 'start') {
markerColor = 'green'; baseSize = 14; // Начальная точка чуть больше
} else if (type === 'end') { } else if (type === 'end') {
markerColor = 'red'; baseSize = 14; // Конечная точка чуть больше
} else if (type === 'intermediate') { } else if (type === 'intermediate') {
markerColor = 'grey'; baseSize = 10; // Промежуточные точки меньше
} }
return L.icon({ const size = Math.round(baseSize * markerSizeMultiplier);
iconUrl: '{% static "leaflet-markers/img/marker-icon-" %}' + markerColor + '.png', const shapeFunc = shapeMap[shape] || shapeMap['circle'];
shadowUrl: '{% static "leaflet-markers/img/marker-shadow.png" %}',
iconSize: [25, 41], return L.divIcon({
iconAnchor: [12, 41], className: 'static-marker',
popupAnchor: [1, -34], iconSize: [size, size],
shadowSize: [41, 41] iconAnchor: [size/2, size/2],
popupAnchor: [0, -size/2],
html: shapeFunc(hexColor, size)
}); });
} }
// Create moving marker icon (colored circle) // Create moving marker icon (current position - larger and more prominent)
function createMovingMarkerIcon(color) { function createMovingMarkerIcon(color, shape) {
const hexColor = colorMap[color] || color; const hexColor = colorMap[color] || color;
const baseSize = 16; // Движущийся маркер немного больше
const size = Math.round(baseSize * markerSizeMultiplier);
const shapeFunc = shapeMap[shape] || shapeMap['circle'];
return L.divIcon({ return L.divIcon({
className: 'current-marker', className: 'current-marker moving-marker',
iconSize: [18, 18], iconSize: [size, size],
iconAnchor: [9, 9], iconAnchor: [size/2, size/2],
html: `<div style="background: ${hexColor}; width: 100%; height: 100%; border-radius: 50%; border: 3px solid white; box-shadow: 0 0 6px rgba(0,0,0,0.5);"></div>` popupAnchor: [0, -size/2],
html: shapeFunc(hexColor, size)
}); });
} }
@@ -335,21 +411,34 @@ function updateDisplay(progress) {
sourcesData.forEach(source => { sourcesData.forEach(source => {
const pos = getPositionAtProgress(source, progress); const pos = getPositionAtProgress(source, progress);
const color = source.color; const color = source.color;
const shape = source.shape;
if (pos) { if (pos) {
// Show/update current marker (moving object - colored circle) // Check if we've reached the end
if (!currentMarkers[source.source_id]) { const isAtEnd = (progress >= 1 || pos.pointIndex === source.points.length - 1) && pos.segmentProgress >= 0.99;
// Get first point name for popup
const firstPointName = source.points && source.points.length > 0 ? source.points[0].name : '';
const popupContent = `<b>ID ${source.source_id}:</b> ${firstPointName}<br><i style="color: #666;">Текущая позиция</i>`;
currentMarkers[source.source_id] = L.marker([pos.lat, pos.lng], { // Show/update current marker (moving object) - hide when at end
icon: createMovingMarkerIcon(color), if (isAtEnd) {
zIndexOffset: 1000 // Remove moving marker when at end point
}).bindPopup(popupContent); if (currentMarkers[source.source_id]) {
sourceLayerGroups[source.source_id].addLayer(currentMarkers[source.source_id]); sourceLayerGroups[source.source_id].removeLayer(currentMarkers[source.source_id]);
delete currentMarkers[source.source_id];
}
} else { } else {
currentMarkers[source.source_id].setLatLng([pos.lat, pos.lng]); // Show/update moving marker
if (!currentMarkers[source.source_id]) {
// Get first point name for popup
const firstPointName = source.points && source.points.length > 0 ? source.points[0].name : '';
const popupContent = `<b>ID ${source.source_id}:</b> ${firstPointName}<br><i style="color: #666;">Текущая позиция</i>`;
currentMarkers[source.source_id] = L.marker([pos.lat, pos.lng], {
icon: createMovingMarkerIcon(color, shape),
zIndexOffset: 1000
}).bindPopup(popupContent);
sourceLayerGroups[source.source_id].addLayer(currentMarkers[source.source_id]);
} else {
currentMarkers[source.source_id].setLatLng([pos.lat, pos.lng]);
}
} }
// Update trail (dashed line showing path) // Update trail (dashed line showing path)
@@ -386,7 +475,7 @@ function updateDisplay(progress) {
} }
const marker = L.marker([point.lat, point.lng], { const marker = L.marker([point.lat, point.lng], {
icon: createStaticMarkerIcon(markerType), icon: createStaticMarkerIcon(markerType, color, shape),
zIndexOffset: markerType === 'start' ? 500 : (markerType === 'end' ? 600 : 100) zIndexOffset: markerType === 'start' ? 500 : (markerType === 'end' ? 600 : 100)
}).bindPopup(`<b>${source.source_name}</b><br>${popupPrefix}${point.name}<br>${point.frequency}<br>${formatDate(point.timestamp)}`); }).bindPopup(`<b>${source.source_name}</b><br>${popupPrefix}${point.name}<br>${point.frequency}<br>${formatDate(point.timestamp)}`);
@@ -401,7 +490,7 @@ function updateDisplay(progress) {
if (!staticMarkers[endMarkerKey] && source.points.length > 1) { if (!staticMarkers[endMarkerKey] && source.points.length > 1) {
const lastPoint = source.points[source.points.length - 1]; const lastPoint = source.points[source.points.length - 1];
const endMarker = L.marker([lastPoint.lat, lastPoint.lng], { const endMarker = L.marker([lastPoint.lat, lastPoint.lng], {
icon: createStaticMarkerIcon('end'), icon: createStaticMarkerIcon('end', color, shape),
zIndexOffset: 600 zIndexOffset: 600
}).bindPopup(`<b>${source.source_name}</b><br><span style="color: red;">■ Конец</span><br>${lastPoint.name}<br>${lastPoint.frequency}<br>${formatDate(lastPoint.timestamp)}`); }).bindPopup(`<b>${source.source_name}</b><br><span style="color: red;">■ Конец</span><br>${lastPoint.name}<br>${lastPoint.frequency}<br>${formatDate(lastPoint.timestamp)}`);
sourceLayerGroups[source.source_id].addLayer(endMarker); sourceLayerGroups[source.source_id].addLayer(endMarker);
@@ -422,19 +511,21 @@ function resetPlayback() {
// Recreate trails // Recreate trails
sourcesData.forEach(source => { sourcesData.forEach(source => {
const color = colorMap[source.color] || source.color; const color = colorMap[source.color] || source.color;
const shape = source.shape;
trailPolylines[source.source_id] = L.polyline([], { trailPolylines[source.source_id] = L.polyline([], {
color: color, color: color,
weight: 3, weight: 2, // Уменьшенная толщина линии
opacity: 0.7, opacity: 0.7,
dashArray: '5, 10' dashArray: '5, 10'
}); });
sourceLayerGroups[source.source_id].addLayer(trailPolylines[source.source_id]); sourceLayerGroups[source.source_id].addLayer(trailPolylines[source.source_id]);
// Add start marker immediately (green) // Add start marker immediately
if (source.points && source.points.length > 0) { if (source.points && source.points.length > 0) {
const firstPoint = source.points[0]; const firstPoint = source.points[0];
const startMarker = L.marker([firstPoint.lat, firstPoint.lng], { const startMarker = L.marker([firstPoint.lat, firstPoint.lng], {
icon: createStaticMarkerIcon('start'), icon: createStaticMarkerIcon('start', color, shape),
zIndexOffset: 500 zIndexOffset: 500
}).bindPopup(`<b>${source.source_name}</b><br><span style="color: green;">▶ Начало</span><br>${firstPoint.name}<br>${firstPoint.frequency}<br>${formatDate(firstPoint.timestamp)}`); }).bindPopup(`<b>${source.source_name}</b><br><span style="color: green;">▶ Начало</span><br>${firstPoint.name}<br>${firstPoint.frequency}<br>${formatDate(firstPoint.timestamp)}`);
sourceLayerGroups[source.source_id].addLayer(startMarker); sourceLayerGroups[source.source_id].addLayer(startMarker);
@@ -446,6 +537,16 @@ function resetPlayback() {
updateDisplay(currentProgress); updateDisplay(currentProgress);
} }
// Update all marker sizes
function updateMarkerSizes() {
// Clear and recreate all markers with new size
pause();
const currentProg = currentProgress;
resetPlayback();
currentProgress = currentProg;
updateDisplay(currentProgress);
}
// Play animation // Play animation
function play() { function play() {
if (playbackInterval) return; if (playbackInterval) return;
@@ -493,6 +594,11 @@ async function loadData() {
// Filter out sources with no points // Filter out sources with no points
sourcesData = sourcesData.filter(s => s.points && s.points.length > 0); sourcesData = sourcesData.filter(s => s.points && s.points.length > 0);
// Assign shapes to sources (cycle through available shapes)
sourcesData.forEach((source, idx) => {
source.shape = availableShapes[idx % availableShapes.length];
});
if (!sourcesData || sourcesData.length === 0) { if (!sourcesData || sourcesData.length === 0) {
document.getElementById('loadingOverlay').innerHTML = ` document.getElementById('loadingOverlay').innerHTML = `
<div class="alert alert-warning"> <div class="alert alert-warning">
@@ -567,6 +673,21 @@ async function loadData() {
speedMultiplier = parseFloat(this.value); speedMultiplier = parseFloat(this.value);
}); });
// Marker size control
const markerSizeSlider = document.getElementById('markerSizeSlider');
const sizeValue = document.getElementById('sizeValue');
markerSizeSlider.addEventListener('input', function() {
markerSizeMultiplier = parseFloat(this.value);
sizeValue.textContent = markerSizeMultiplier.toFixed(1) + 'x';
updateMarkerSizes();
});
// Disable map scroll/zoom when mouse is over marker size control
const markerSizeControl = document.querySelector('.marker-size-control');
L.DomEvent.disableScrollPropagation(markerSizeControl);
L.DomEvent.disableClickPropagation(markerSizeControl);
} catch (error) { } catch (error) {
console.error('Error loading data:', error); console.error('Error loading data:', error);
document.getElementById('loadingOverlay').innerHTML = ` document.getElementById('loadingOverlay').innerHTML = `
@@ -593,22 +714,12 @@ function addLegend() {
sourcesData.forEach(source => { sourcesData.forEach(source => {
const color = colorMap[source.color] || source.color; const color = colorMap[source.color] || source.color;
const shape = source.shape;
const points = source.points; const points = source.points;
// Get marker color for this source // Create shape preview
const markerColorMap = { const shapeFunc = shapeMap[shape] || shapeMap['circle'];
'red': 'red', const shapePreview = shapeFunc(color, 16);
'blue': 'blue',
'green': 'green',
'purple': 'violet',
'orange': 'orange',
'cyan': 'blue',
'magenta': 'red',
'yellow': 'yellow',
'lime': 'green',
'pink': 'red'
};
const markerColor = markerColorMap[source.color] || 'blue';
// Get first point name and time info // Get first point name and time info
let firstPointName = ''; let firstPointName = '';
@@ -627,11 +738,12 @@ function addLegend() {
html += ` html += `
<div class="legend-item" style="flex-direction: column; align-items: flex-start; margin-bottom: 8px;"> <div class="legend-item" style="flex-direction: column; align-items: flex-start; margin-bottom: 8px;">
<div style="display: flex; align-items: center;"> <div style="display: flex; align-items: center;">
<img src="{% static "leaflet-markers/img/marker-icon-" %}${markerColor}.png" <div style="width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; margin-right: 6px;">
style="width: 18px; height: 30px; margin-right: 6px;"> ${shapePreview}
</div>
<span><strong>ID ${source.source_id}:</strong> ${firstPointName}</span> <span><strong>ID ${source.source_id}:</strong> ${firstPointName}</span>
</div> </div>
<div style="margin-left: 24px;"> <div style="margin-left: 26px;">
<small style="color: #666;">${source.points_count} точек</small> <small style="color: #666;">${source.points_count} точек</small>
${timeInfo} ${timeInfo}
</div> </div>
@@ -639,31 +751,6 @@ function addLegend() {
`; `;
}); });
html += '<div class="legend-section"><strong>Маркеры:</strong></div>';
html += `
<div class="legend-item">
<img src="{% static "leaflet-markers/img/marker-icon-green.png" %}"
style="width: 18px; height: 30px; margin-right: 6px;">
<span>Начальная точка</span>
</div>
<div class="legend-item">
<img src="{% static "leaflet-markers/img/marker-icon-red.png" %}"
style="width: 18px; height: 30px; margin-right: 6px;">
<span>Конечная точка</span>
</div>
<div class="legend-item">
<img src="{% static "leaflet-markers/img/marker-icon-grey.png" %}"
style="width: 18px; height: 30px; margin-right: 6px;">
<span>Промежуточная точка</span>
</div>
<div class="legend-item">
<div style="width: 18px; height: 18px; border-radius: 50%; background: #007bff; border: 3px solid white; box-shadow: 0 0 4px rgba(0,0,0,0.4); margin-right: 6px;"></div>
<span>Движущийся объект (цвет по объекту)</span>
</div>
`;
html += '<div class="legend-section"><small style="color: #666;">Все объекты движутся<br>с одинаковой скоростью</small></div>';
div.innerHTML = html; div.innerHTML = html;
return div; return div;
}; };

View File

@@ -124,7 +124,7 @@
</div> </div>
<div class="averaging-container"> <div class="averaging-container">
<h2>Усреднение точек по источникам</h2> <h2>Усреднение точек по объектам</h2>
<div class="form-section"> <div class="form-section">
<div class="row"> <div class="row">
@@ -156,7 +156,7 @@
<div class="table-section"> <div class="table-section">
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
<div> <div>
<h5>Источники <span id="source-count" class="badge bg-primary">0</span></h5> <h5>Объекты <span id="source-count" class="badge bg-primary">0</span></h5>
</div> </div>
<div class="btn-group-custom"> <div class="btn-group-custom">
<button id="export-xlsx" class="btn btn-success" disabled> <button id="export-xlsx" class="btn btn-success" disabled>
@@ -180,7 +180,7 @@
<div class="modal-dialog modal-xl"> <div class="modal-dialog modal-xl">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title" id="sourceDetailsModalLabel">Детали источника</h5> <h5 class="modal-title" id="sourceDetailsModalLabel">Детали объекта</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body" id="modal-body-content"> <div class="modal-body" id="modal-body-content">
@@ -279,7 +279,7 @@ document.addEventListener('DOMContentLoaded', function() {
{column: "frequency", dir: "asc"} {column: "frequency", dir: "asc"}
], ],
columns: [ columns: [
{title: "Источник", field: "source_name", minWidth: 180, widthGrow: 2}, {title: "Объект", field: "source_name", minWidth: 180, widthGrow: 2},
{title: "Групп", field: "groups_count", minWidth: 70, hozAlign: "center"}, {title: "Групп", field: "groups_count", minWidth: 70, hozAlign: "center"},
{title: "Точек", field: "total_points", minWidth: 70, hozAlign: "center"}, {title: "Точек", field: "total_points", minWidth: 70, hozAlign: "center"},
{title: "Частота", field: "frequency", minWidth: 100, sorter: "number"}, {title: "Частота", field: "frequency", minWidth: 100, sorter: "number"},
@@ -327,7 +327,7 @@ document.addEventListener('DOMContentLoaded', function() {
// Delete source // Delete source
function deleteSource(sourceIdx) { function deleteSource(sourceIdx) {
//if (!confirm('Удалить этот источник со всеми группами?')) return; //if (!confirm('Удалить этот объект со всеми группами?')) return;
allSourcesData.splice(sourceIdx, 1); allSourcesData.splice(sourceIdx, 1);
updateSourcesTable(); updateSourcesTable();
} }
@@ -338,7 +338,7 @@ document.addEventListener('DOMContentLoaded', function() {
const source = allSourcesData[sourceIdx]; const source = allSourcesData[sourceIdx];
if (!source) return; if (!source) return;
document.getElementById('sourceDetailsModalLabel').textContent = `Источник: ${source.source_name}`; document.getElementById('sourceDetailsModalLabel').textContent = `Объект: ${source.source_name}`;
renderModalContent(); renderModalContent();
const modal = new bootstrap.Modal(document.getElementById('sourceDetailsModal')); const modal = new bootstrap.Modal(document.getElementById('sourceDetailsModal'));
@@ -619,7 +619,7 @@ document.addEventListener('DOMContentLoaded', function() {
allSourcesData.forEach(source => { allSourcesData.forEach(source => {
source.groups.forEach(group => { source.groups.forEach(group => {
summaryData.push({ summaryData.push({
'Источник': source.source_name, 'Объект': source.source_name,
'Частота, МГц': group.frequency, 'Частота, МГц': group.frequency,
'Полоса, МГц': group.freq_range, 'Полоса, МГц': group.freq_range,
'Символьная скорость, БОД': group.bod_velocity, 'Символьная скорость, БОД': group.bod_velocity,
@@ -646,7 +646,7 @@ document.addEventListener('DOMContentLoaded', function() {
source.groups.forEach(group => { source.groups.forEach(group => {
group.points.forEach(point => { group.points.forEach(point => {
allPointsData.push({ allPointsData.push({
'Источник': source.source_name, 'Объект': source.source_name,
'ID точки': point.id, 'ID точки': point.id,
'Имя точки': point.name, 'Имя точки': point.name,
'Частота, МГц': point.frequency, 'Частота, МГц': point.frequency,

View File

@@ -216,7 +216,7 @@
filterPolygon.addTo(map); filterPolygon.addTo(map);
// Добавляем popup с информацией // Добавляем popup с информацией
filterPolygon.bindPopup('<strong>Область фильтра</strong><br>Отображаются только источники с точками в этой области'); filterPolygon.bindPopup('<strong>Область фильтра</strong><br>Отображаются только объекты с точками в этой области');
// Если нет других точек, центрируем карту на полигоне // Если нет других точек, центрируем карту на полигоне
{% if not groups %} {% if not groups %}

View File

@@ -154,7 +154,7 @@ class ShowSourcesMapView(LoginRequiredMixin, View):
points.append( points.append(
{ {
"point": (coords.x, coords.y), # (lon, lat) "point": (coords.x, coords.y), # (lon, lat)
"source_id": f"Источник #{source.id}", "source_id": f"Объект #{source.id}",
} }
) )

View File

@@ -0,0 +1,20 @@
# Generated by Django 5.2.7 on 2025-12-03 07:51
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('mainapp', '0017_add_satellite_alternative_name'),
('mapsapp', '0002_alter_transponders_snr'),
]
operations = [
migrations.AlterField(
model_name='transponders',
name='sat_id',
field=models.ForeignKey(help_text='Спутник, которому принадлежит транспондер', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tran_satellite', to='mainapp.satellite', verbose_name='Спутник'),
),
]

View File

@@ -103,7 +103,8 @@ class Transponders(models.Model):
) )
sat_id = models.ForeignKey( sat_id = models.ForeignKey(
Satellite, Satellite,
on_delete=models.PROTECT, on_delete=models.SET_NULL,
null=True,
related_name="tran_satellite", related_name="tran_satellite",
verbose_name="Спутник", verbose_name="Спутник",
db_index=True, db_index=True,

View File

@@ -64,5 +64,12 @@ def test_celery_connection():
print("=" * 60) print("=" * 60)
return True return True
if __name__ == "__main__": # if __name__ == "__main__":
test_celery_connection() # test_celery_connection()
import requests
url = f"https://www.lyngsat.com/europe.html"
payload = {"cmd": "request.get", "url": url, "maxTimeout": 60000}
response = requests.post("http://localhost:8191/v1", json=payload)
print(response.content)