# Django imports from django.core.exceptions import ValidationError from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from django.db.models import ExpressionWrapper, F from django.db.models.functions import Abs # Local imports from mainapp.models import Polarization, Satellite, get_default_polarization class Transponders(models.Model): """ Модель транспондера спутника. Хранит информацию о частотах uplink/downlink, зоне покрытия и поляризации. """ # Основные поля name = models.CharField( max_length=30, null=True, blank=True, verbose_name="Название транспондера", db_index=True, help_text="Название транспондера" ) downlink = models.FloatField( blank=True, null=True, verbose_name="Downlink", validators=[MinValueValidator(0), MaxValueValidator(50000)], help_text="Частота downlink в МГц (0-50000)" ) frequency_range = models.FloatField( blank=True, null=True, verbose_name="Полоса", validators=[MinValueValidator(0), MaxValueValidator(1000)], help_text="Полоса частот в МГц (0-1000)" ) uplink = models.FloatField( blank=True, null=True, verbose_name="Uplink", validators=[MinValueValidator(0), MaxValueValidator(50000)], help_text="Частота uplink в МГц (0-50000)" ) zone_name = models.CharField( max_length=255, blank=True, null=True, verbose_name="Название зоны", db_index=True, help_text="Название зоны покрытия транспондера" ) # Связи polarization = models.ForeignKey( Polarization, default=get_default_polarization, on_delete=models.SET_DEFAULT, related_name="tran_polarizations", null=True, blank=True, verbose_name="Поляризация", help_text="Поляризация сигнала" ) sat_id = models.ForeignKey( Satellite, on_delete=models.PROTECT, related_name="tran_satellite", verbose_name="Спутник", db_index=True, help_text="Спутник, которому принадлежит транспондер" ) # Вычисляемые поля 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 clean(self): """Валидация на уровне модели""" super().clean() # Проверка что downlink и uplink заданы if self.downlink and self.uplink: # Обычно uplink выше downlink для спутниковой связи if self.uplink < self.downlink: raise ValidationError({ 'uplink': 'Частота uplink обычно выше частоты downlink' }) def __str__(self): if self.name: return self.name return f"Транспондер {self.sat_id.name if self.sat_id else 'Unknown'}" class Meta: verbose_name = "Транспондер" verbose_name_plural = "Транспондеры" ordering = ['sat_id', 'downlink'] indexes = [ models.Index(fields=['sat_id', 'downlink']), models.Index(fields=['sat_id', 'zone_name']), ]