# 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, CustomUser 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="Название зоны покрытия транспондера", ) snr = models.FloatField( blank=True, null=True, verbose_name="Полоса", # validators=[MinValueValidator(0), MaxValueValidator(1000)], help_text="Полоса частот в МГц (0-1000)", ) created_at = models.DateTimeField( auto_now_add=True, verbose_name="Дата создания", help_text="Дата и время создания записи", ) created_by = models.ForeignKey( CustomUser, on_delete=models.SET_NULL, related_name="transponder_created", null=True, blank=True, verbose_name="Создан пользователем", help_text="Пользователь, создавший запись", ) updated_at = models.DateTimeField( auto_now=True, verbose_name="Дата последнего изменения", help_text="Дата и время последнего изменения", ) updated_by = models.ForeignKey( CustomUser, on_delete=models.SET_NULL, related_name="transponder_updated", null=True, blank=True, verbose_name="Изменен пользователем", 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"]), ]