rework main models

This commit is contained in:
2025-10-30 09:19:55 +03:00
parent 178854c6ba
commit 94df5171db
25 changed files with 744 additions and 190 deletions

View File

@@ -5,20 +5,24 @@ from more_admin_filters import MultiSelectDropdownFilter, MultiSelectFilter, Mul
from import_export.admin import ImportExportActionModelAdmin
@admin.register(Transponders)
class PolarizationAdmin(ImportExportActionModelAdmin, admin.ModelAdmin):
class TranspondersAdmin(ImportExportActionModelAdmin, admin.ModelAdmin):
list_display = (
"sat_id",
"name",
"zone_name",
"frequency",
"downlink",
"uplink",
"frequency_range",
"transfer",
"polarization",
)
list_filter = (
("polarization", MultiSelectRelatedDropdownFilter),
("sat_id", MultiSelectRelatedDropdownFilter),
("frequency", NumericRangeFilterBuilder()),
# ("frequency", NumericRangeFilterBuilder()),
"zone_name"
)
search_fields = ("name",)
search_fields = ("name", "sat_id__name")
ordering = ("name",)
# def sat_name(self, obj):
# return

View File

@@ -0,0 +1,34 @@
# Generated by Django 5.2.7 on 2025-10-27 12:20
import django.db.models.expressions
import django.db.models.functions.math
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('mapsapp', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='transponders',
name='frequency',
),
migrations.AddField(
model_name='transponders',
name='downlink',
field=models.FloatField(blank=True, null=True, verbose_name='Downlink'),
),
migrations.AddField(
model_name='transponders',
name='uplink',
field=models.FloatField(blank=True, null=True, verbose_name='Uplink'),
),
migrations.AddField(
model_name='transponders',
name='transfer',
field=models.GeneratedField(db_persist=True, expression=models.ExpressionWrapper(django.db.models.functions.math.Abs(django.db.models.expressions.CombinedExpression(models.F('downlink'), '-', models.F('uplink'))), output_field=models.FloatField()), null=True, output_field=models.FloatField(), verbose_name='Расстояние между купсатом и гео, км'),
),
]

View File

@@ -0,0 +1,20 @@
# Generated by Django 5.2.7 on 2025-10-27 13:10
import django.db.models.expressions
import django.db.models.functions.math
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('mapsapp', '0002_remove_transponders_frequency_transponders_downlink_and_more'),
]
operations = [
migrations.AlterField(
model_name='transponders',
name='transfer',
field=models.GeneratedField(db_persist=True, expression=models.ExpressionWrapper(django.db.models.functions.math.Abs(django.db.models.expressions.CombinedExpression(models.F('downlink'), '-', models.F('uplink'))), output_field=models.FloatField()), null=True, output_field=models.FloatField(), verbose_name='Перенос'),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.2.7 on 2025-10-28 05:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('mapsapp', '0003_alter_transponders_transfer'),
]
operations = [
migrations.AlterField(
model_name='transponders',
name='zone_name',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Название зоны'),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.2.7 on 2025-10-29 14:00
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('mapsapp', '0004_alter_transponders_zone_name'),
]
operations = [
migrations.AlterField(
model_name='transponders',
name='frequency_range',
field=models.FloatField(blank=True, null=True, verbose_name='Полоса'),
),
]

View File

@@ -1,15 +1,27 @@
from django.db import models
from mainapp.models import Satellite, Polarization, get_default_polarization
from django.db.models import F, ExpressionWrapper
from django.db.models.functions import Abs
class Transponders(models.Model):
name = models.CharField(max_length=30, null=True, blank=True, verbose_name="Название транспондера")
frequency = models.FloatField(blank=True, null=True, verbose_name="Центральная частота")
frequency_range = models.FloatField(blank=True, null=True, verbose_name="Полоса частот")
zone_name = models.CharField(max_length=60, blank=True, null=True, verbose_name="Название зоны")
downlink = models.FloatField(blank=True, null=True, verbose_name="Downlink")
frequency_range = models.FloatField(blank=True, null=True, verbose_name="Полоса")
uplink = models.FloatField(blank=True, null=True, verbose_name="Uplink")
zone_name = models.CharField(max_length=255, blank=True, null=True, verbose_name="Название зоны")
polarization = models.ForeignKey(
Polarization, default=get_default_polarization, on_delete=models.SET_DEFAULT, related_name="tran_polarizations", null=True, blank=True, verbose_name="Поляризация"
)
sat_id = models.ForeignKey(Satellite, on_delete=models.PROTECT, related_name="tran_satellite", verbose_name="Спутник")
transfer =models.GeneratedField(
expression=ExpressionWrapper(
Abs(F('downlink') - F('uplink')),
output_field=models.FloatField()
),
output_field=models.FloatField(),
db_persist=True,
null=True, blank=True, verbose_name="Перенос"
)
def __str__(self):
return self.name

View File

@@ -3,6 +3,7 @@ import re
import json
from .models import Transponders
from mainapp.models import Polarization, Satellite
from io import BytesIO
def search_satellite_on_page(data: dict, satellite_name: str):
for pos, value in data.get('page', {}).get('positions').items():
@@ -90,3 +91,68 @@ def parse_transponders_from_json(filepath: str):
)
tran_obj.save()
from lxml import etree
def parse_transponders_from_xml(data_in: BytesIO):
tree = etree.parse(data_in)
ns = {
'i': 'http://www.w3.org/2001/XMLSchema-instance',
'ns': 'http://schemas.datacontract.org/2004/07/Geolocation.Domain.Utils.Repository.SatellitesSerialization.Memos',
'tr': 'http://schemas.datacontract.org/2004/07/Geolocation.Common.Extensions'
}
satellites = tree.xpath('//ns:SatelliteMemo', namespaces=ns)
for sat in satellites[:]:
name = sat.xpath('./ns:name/text()', namespaces=ns)[0]
if name == 'X' or 'DONT USE' in name:
continue
norad = sat.xpath('./ns:norad/text()', namespaces=ns)
beams = sat.xpath('.//ns:BeamMemo', namespaces=ns)
zones = {}
for zone in beams:
zone_name = zone.xpath('./ns:name/text()', namespaces=ns)[0] if zone.xpath('./ns:name/text()', namespaces=ns) else '-'
zones[zone.xpath('./ns:id/text()', namespaces=ns)[0]] = {
"name": zone_name,
"pol": zone.xpath('./ns:polarization/text()', namespaces=ns)[0],
}
transponders = sat.xpath('.//ns:TransponderMemo', namespaces=ns)
for transponder in transponders:
tr_id = transponder.xpath('./ns:downlinkBeamId/text()', namespaces=ns)[0]
downlink_start = float(transponder.xpath('./ns:downlinkFrequency/tr:start/text()', namespaces=ns)[0])
downlink_end = float(transponder.xpath('./ns:downlinkFrequency/tr:end/text()', namespaces=ns)[0])
uplink_start = float(transponder.xpath('./ns:uplinkFrequency/tr:start/text()', namespaces=ns)[0])
uplink_end = float(transponder.xpath('./ns:uplinkFrequency/tr:end/text()', namespaces=ns)[0])
tr_data = zones[tr_id]
# p = tr_data['pol'][0] if tr_data['pol'] else '-'
match tr_data['pol']:
case 'Horizontal':
pol = 'Горизонтальная'
case 'Vertical':
pol = 'Вертикальная'
case 'CircularRight':
pol = 'Правая'
case 'CircularLeft':
pol = 'Левая'
case _:
pol = '-'
tr_name = transponder.xpath('./ns:name/text()', namespaces=ns)[0]
pol_obj, _ = Polarization.objects.get_or_create(name=pol)
sat_obj, _ = Satellite.objects.get_or_create(
name=name,
defaults={
"norad": int(norad[0]) if norad else -1
})
trans_obj, _ = Transponders.objects.get_or_create(
polarization=pol_obj,
downlink=(downlink_start+downlink_end)/2/1000000,
uplink=(uplink_start+uplink_end)/2/1000000,
frequency_range=abs(downlink_end-downlink_start)/1000000,
name=tr_name,
defaults={
"zone_name": tr_data['name'],
"sat_id": sat_obj,
}
)
trans_obj.save()