Настроил сеелери, начал привязку lyngsat
This commit is contained in:
@@ -1,301 +1,301 @@
|
||||
# Django imports
|
||||
from django import forms
|
||||
|
||||
# Local imports
|
||||
from .models import Geo, Modulation, ObjItem, Parameter, Polarization, Satellite, Standard
|
||||
|
||||
class UploadFileForm(forms.Form):
|
||||
file = forms.FileField(
|
||||
label="Выберите файл",
|
||||
widget=forms.FileInput(attrs={
|
||||
'class': 'form-file-input'
|
||||
})
|
||||
)
|
||||
|
||||
|
||||
class LoadExcelData(forms.Form):
|
||||
file = forms.FileField(
|
||||
label="Выберите Excel файл",
|
||||
widget=forms.FileInput(attrs={
|
||||
'class': 'form-control',
|
||||
'accept': '.xlsx,.xls'
|
||||
})
|
||||
)
|
||||
sat_choice = forms.ModelChoiceField(
|
||||
queryset=Satellite.objects.all(),
|
||||
label="Выберите спутник",
|
||||
widget=forms.Select(attrs={
|
||||
'class': 'form-select'
|
||||
})
|
||||
)
|
||||
number_input = forms.IntegerField(
|
||||
label="Введите число объектов",
|
||||
min_value=0,
|
||||
widget=forms.NumberInput(attrs={
|
||||
'class': 'form-control'
|
||||
})
|
||||
)
|
||||
|
||||
class LoadCsvData(forms.Form):
|
||||
file = forms.FileField(
|
||||
label="Выберите CSV файл",
|
||||
widget=forms.FileInput(attrs={
|
||||
'class': 'form-control',
|
||||
'accept': '.csv'
|
||||
})
|
||||
)
|
||||
|
||||
class UploadVchLoad(UploadFileForm):
|
||||
sat_choice = forms.ModelChoiceField(
|
||||
queryset=Satellite.objects.all(),
|
||||
label="Выберите спутник",
|
||||
widget=forms.Select(attrs={
|
||||
'class': 'form-select'
|
||||
})
|
||||
)
|
||||
|
||||
|
||||
class VchLinkForm(forms.Form):
|
||||
sat_choice = forms.ModelChoiceField(
|
||||
queryset=Satellite.objects.all(),
|
||||
label="Выберите спутник",
|
||||
widget=forms.Select(attrs={
|
||||
'class': 'form-select'
|
||||
})
|
||||
)
|
||||
# ku_range = forms.ChoiceField(
|
||||
# choices=[(9750.0, '9750'), (10750.0, '10750')],
|
||||
# # coerce=lambda x: x == 'True',
|
||||
# widget=forms.Select(attrs={'class': 'form-select'}),
|
||||
# label='Выбор диапазона'
|
||||
# )
|
||||
value1 = forms.FloatField(
|
||||
label="Первое число",
|
||||
widget=forms.NumberInput(attrs={
|
||||
'class': 'form-control',
|
||||
'placeholder': 'Введите первое число'
|
||||
})
|
||||
)
|
||||
value2 = forms.FloatField(
|
||||
label="Второе число",
|
||||
widget=forms.NumberInput(attrs={
|
||||
'class': 'form-control',
|
||||
'placeholder': 'Введите второе число'
|
||||
})
|
||||
)
|
||||
|
||||
|
||||
class NewEventForm(forms.Form):
|
||||
# sat_choice = forms.ModelChoiceField(
|
||||
# queryset=Satellite.objects.all(),
|
||||
# label="Выберите спутник",
|
||||
# widget=forms.Select(attrs={
|
||||
# 'class': 'form-select'
|
||||
# })
|
||||
# )
|
||||
# pol_choice = forms.ModelChoiceField(
|
||||
# queryset=Polarization.objects.all(),
|
||||
# label="Выберите поляризацию",
|
||||
# widget=forms.Select(attrs={
|
||||
# 'class': 'form-select'
|
||||
# })
|
||||
# )
|
||||
file = forms.FileField(
|
||||
label="Выберите файл",
|
||||
widget=forms.FileInput(attrs={
|
||||
'class': 'form-control',
|
||||
'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):
|
||||
"""
|
||||
Форма для создания и редактирования параметров ВЧ загрузки.
|
||||
|
||||
Работает с одним экземпляром Parameter, связанным с ObjItem через OneToOne связь.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Parameter
|
||||
fields = [
|
||||
'id_satellite', 'frequency', 'freq_range', 'polarization',
|
||||
'bod_velocity', 'modulation', 'snr', 'standard'
|
||||
]
|
||||
widgets = {
|
||||
'id_satellite': forms.Select(attrs={
|
||||
'class': 'form-select',
|
||||
'required': True
|
||||
}),
|
||||
'frequency': forms.NumberInput(attrs={
|
||||
'class': 'form-control',
|
||||
'step': '0.000001',
|
||||
'min': '0',
|
||||
'max': '50000',
|
||||
'placeholder': 'Введите частоту в МГц'
|
||||
}),
|
||||
'freq_range': forms.NumberInput(attrs={
|
||||
'class': 'form-control',
|
||||
'step': '0.000001',
|
||||
'min': '0',
|
||||
'max': '1000',
|
||||
'placeholder': 'Введите полосу частот в МГц'
|
||||
}),
|
||||
'bod_velocity': forms.NumberInput(attrs={
|
||||
'class': 'form-control',
|
||||
'step': '0.001',
|
||||
'min': '0',
|
||||
'placeholder': 'Введите символьную скорость в БОД'
|
||||
}),
|
||||
'snr': forms.NumberInput(attrs={
|
||||
'class': 'form-control',
|
||||
'step': '0.001',
|
||||
'min': '-50',
|
||||
'max': '100',
|
||||
'placeholder': 'Введите ОСШ в дБ'
|
||||
}),
|
||||
'polarization': forms.Select(attrs={'class': 'form-select'}),
|
||||
'modulation': forms.Select(attrs={'class': 'form-select'}),
|
||||
'standard': forms.Select(attrs={'class': 'form-select'}),
|
||||
}
|
||||
labels = {
|
||||
'id_satellite': 'Спутник',
|
||||
'frequency': 'Частота (МГц)',
|
||||
'freq_range': 'Полоса частот (МГц)',
|
||||
'polarization': 'Поляризация',
|
||||
'bod_velocity': 'Символьная скорость (БОД)',
|
||||
'modulation': 'Модуляция',
|
||||
'snr': 'ОСШ (дБ)',
|
||||
'standard': 'Стандарт',
|
||||
}
|
||||
help_texts = {
|
||||
'frequency': 'Частота в диапазоне от 0 до 50000 МГц',
|
||||
'freq_range': 'Полоса частот в диапазоне от 0 до 1000 МГц',
|
||||
'bod_velocity': 'Символьная скорость должна быть положительной',
|
||||
'snr': 'Отношение сигнал/шум в диапазоне от -50 до 100 дБ',
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# Динамически загружаем choices для select полей
|
||||
self.fields['id_satellite'].queryset = Satellite.objects.all().order_by('name')
|
||||
self.fields['polarization'].queryset = Polarization.objects.all().order_by('name')
|
||||
self.fields['modulation'].queryset = Modulation.objects.all().order_by('name')
|
||||
self.fields['standard'].queryset = Standard.objects.all().order_by('name')
|
||||
|
||||
# Делаем спутник обязательным полем
|
||||
self.fields['id_satellite'].required = True
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
Дополнительная валидация формы.
|
||||
|
||||
Проверяет соотношение между частотой, полосой частот и символьной скоростью.
|
||||
"""
|
||||
cleaned_data = super().clean()
|
||||
frequency = cleaned_data.get('frequency')
|
||||
freq_range = cleaned_data.get('freq_range')
|
||||
bod_velocity = cleaned_data.get('bod_velocity')
|
||||
|
||||
# Проверка что частота больше полосы частот
|
||||
if frequency and freq_range:
|
||||
if freq_range > frequency:
|
||||
self.add_error('freq_range', 'Полоса частот не может быть больше частоты')
|
||||
|
||||
# Проверка что символьная скорость соответствует полосе частот
|
||||
if bod_velocity and freq_range:
|
||||
if bod_velocity > freq_range * 1000000: # Конвертация МГц в Гц
|
||||
self.add_error('bod_velocity', 'Символьная скорость не может превышать полосу частот')
|
||||
|
||||
return cleaned_data
|
||||
|
||||
class GeoForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Geo
|
||||
fields = ['location', 'comment', 'is_average']
|
||||
widgets = {
|
||||
'location': forms.TextInput(attrs={'class': 'form-control'}),
|
||||
'comment': forms.TextInput(attrs={'class': 'form-control'}),
|
||||
'is_average': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
|
||||
}
|
||||
|
||||
class ObjItemForm(forms.ModelForm):
|
||||
"""
|
||||
Форма для создания и редактирования объектов (источников сигнала).
|
||||
|
||||
Работает с моделью ObjItem. Параметры ВЧ загрузки обрабатываются отдельно
|
||||
через ParameterForm с использованием OneToOne связи.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = ObjItem
|
||||
fields = ['name']
|
||||
widgets = {
|
||||
'name': forms.TextInput(attrs={
|
||||
'class': 'form-control',
|
||||
'placeholder': 'Введите название объекта',
|
||||
'maxlength': '100'
|
||||
}),
|
||||
}
|
||||
labels = {
|
||||
'name': 'Название объекта',
|
||||
}
|
||||
help_texts = {
|
||||
'name': 'Уникальное название объекта/источника сигнала',
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
# Делаем поле name необязательным, так как оно может быть пустым
|
||||
self.fields['name'].required = False
|
||||
|
||||
def clean_name(self):
|
||||
"""
|
||||
Валидация поля name.
|
||||
|
||||
Проверяет что название не состоит только из пробелов.
|
||||
"""
|
||||
name = self.cleaned_data.get('name')
|
||||
|
||||
if name:
|
||||
# Удаляем лишние пробелы
|
||||
name = name.strip()
|
||||
|
||||
# Проверяем что после удаления пробелов что-то осталось
|
||||
if not name:
|
||||
raise forms.ValidationError('Название не может состоять только из пробелов')
|
||||
|
||||
# Django imports
|
||||
from django import forms
|
||||
|
||||
# Local imports
|
||||
from .models import Geo, Modulation, ObjItem, Parameter, Polarization, Satellite, Standard
|
||||
|
||||
class UploadFileForm(forms.Form):
|
||||
file = forms.FileField(
|
||||
label="Выберите файл",
|
||||
widget=forms.FileInput(attrs={
|
||||
'class': 'form-file-input'
|
||||
})
|
||||
)
|
||||
|
||||
|
||||
class LoadExcelData(forms.Form):
|
||||
file = forms.FileField(
|
||||
label="Выберите Excel файл",
|
||||
widget=forms.FileInput(attrs={
|
||||
'class': 'form-control',
|
||||
'accept': '.xlsx,.xls'
|
||||
})
|
||||
)
|
||||
sat_choice = forms.ModelChoiceField(
|
||||
queryset=Satellite.objects.all(),
|
||||
label="Выберите спутник",
|
||||
widget=forms.Select(attrs={
|
||||
'class': 'form-select'
|
||||
})
|
||||
)
|
||||
number_input = forms.IntegerField(
|
||||
label="Введите число объектов",
|
||||
min_value=0,
|
||||
widget=forms.NumberInput(attrs={
|
||||
'class': 'form-control'
|
||||
})
|
||||
)
|
||||
|
||||
class LoadCsvData(forms.Form):
|
||||
file = forms.FileField(
|
||||
label="Выберите CSV файл",
|
||||
widget=forms.FileInput(attrs={
|
||||
'class': 'form-control',
|
||||
'accept': '.csv'
|
||||
})
|
||||
)
|
||||
|
||||
class UploadVchLoad(UploadFileForm):
|
||||
sat_choice = forms.ModelChoiceField(
|
||||
queryset=Satellite.objects.all(),
|
||||
label="Выберите спутник",
|
||||
widget=forms.Select(attrs={
|
||||
'class': 'form-select'
|
||||
})
|
||||
)
|
||||
|
||||
|
||||
class VchLinkForm(forms.Form):
|
||||
sat_choice = forms.ModelChoiceField(
|
||||
queryset=Satellite.objects.all(),
|
||||
label="Выберите спутник",
|
||||
widget=forms.Select(attrs={
|
||||
'class': 'form-select'
|
||||
})
|
||||
)
|
||||
# ku_range = forms.ChoiceField(
|
||||
# choices=[(9750.0, '9750'), (10750.0, '10750')],
|
||||
# # coerce=lambda x: x == 'True',
|
||||
# widget=forms.Select(attrs={'class': 'form-select'}),
|
||||
# label='Выбор диапазона'
|
||||
# )
|
||||
value1 = forms.FloatField(
|
||||
label="Первое число",
|
||||
widget=forms.NumberInput(attrs={
|
||||
'class': 'form-control',
|
||||
'placeholder': 'Введите первое число'
|
||||
})
|
||||
)
|
||||
value2 = forms.FloatField(
|
||||
label="Второе число",
|
||||
widget=forms.NumberInput(attrs={
|
||||
'class': 'form-control',
|
||||
'placeholder': 'Введите второе число'
|
||||
})
|
||||
)
|
||||
|
||||
|
||||
class NewEventForm(forms.Form):
|
||||
# sat_choice = forms.ModelChoiceField(
|
||||
# queryset=Satellite.objects.all(),
|
||||
# label="Выберите спутник",
|
||||
# widget=forms.Select(attrs={
|
||||
# 'class': 'form-select'
|
||||
# })
|
||||
# )
|
||||
# pol_choice = forms.ModelChoiceField(
|
||||
# queryset=Polarization.objects.all(),
|
||||
# label="Выберите поляризацию",
|
||||
# widget=forms.Select(attrs={
|
||||
# 'class': 'form-select'
|
||||
# })
|
||||
# )
|
||||
file = forms.FileField(
|
||||
label="Выберите файл",
|
||||
widget=forms.FileInput(attrs={
|
||||
'class': 'form-control',
|
||||
'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):
|
||||
"""
|
||||
Форма для создания и редактирования параметров ВЧ загрузки.
|
||||
|
||||
Работает с одним экземпляром Parameter, связанным с ObjItem через OneToOne связь.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Parameter
|
||||
fields = [
|
||||
'id_satellite', 'frequency', 'freq_range', 'polarization',
|
||||
'bod_velocity', 'modulation', 'snr', 'standard'
|
||||
]
|
||||
widgets = {
|
||||
'id_satellite': forms.Select(attrs={
|
||||
'class': 'form-select',
|
||||
'required': True
|
||||
}),
|
||||
'frequency': forms.NumberInput(attrs={
|
||||
'class': 'form-control',
|
||||
'step': '0.000001',
|
||||
'min': '0',
|
||||
'max': '50000',
|
||||
'placeholder': 'Введите частоту в МГц'
|
||||
}),
|
||||
'freq_range': forms.NumberInput(attrs={
|
||||
'class': 'form-control',
|
||||
'step': '0.000001',
|
||||
'min': '0',
|
||||
'max': '1000',
|
||||
'placeholder': 'Введите полосу частот в МГц'
|
||||
}),
|
||||
'bod_velocity': forms.NumberInput(attrs={
|
||||
'class': 'form-control',
|
||||
'step': '0.001',
|
||||
'min': '0',
|
||||
'placeholder': 'Введите символьную скорость в БОД'
|
||||
}),
|
||||
'snr': forms.NumberInput(attrs={
|
||||
'class': 'form-control',
|
||||
'step': '0.001',
|
||||
'min': '-50',
|
||||
'max': '100',
|
||||
'placeholder': 'Введите ОСШ в дБ'
|
||||
}),
|
||||
'polarization': forms.Select(attrs={'class': 'form-select'}),
|
||||
'modulation': forms.Select(attrs={'class': 'form-select'}),
|
||||
'standard': forms.Select(attrs={'class': 'form-select'}),
|
||||
}
|
||||
labels = {
|
||||
'id_satellite': 'Спутник',
|
||||
'frequency': 'Частота (МГц)',
|
||||
'freq_range': 'Полоса частот (МГц)',
|
||||
'polarization': 'Поляризация',
|
||||
'bod_velocity': 'Символьная скорость (БОД)',
|
||||
'modulation': 'Модуляция',
|
||||
'snr': 'ОСШ (дБ)',
|
||||
'standard': 'Стандарт',
|
||||
}
|
||||
help_texts = {
|
||||
'frequency': 'Частота в диапазоне от 0 до 50000 МГц',
|
||||
'freq_range': 'Полоса частот в диапазоне от 0 до 1000 МГц',
|
||||
'bod_velocity': 'Символьная скорость должна быть положительной',
|
||||
'snr': 'Отношение сигнал/шум в диапазоне от -50 до 100 дБ',
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# Динамически загружаем choices для select полей
|
||||
self.fields['id_satellite'].queryset = Satellite.objects.all().order_by('name')
|
||||
self.fields['polarization'].queryset = Polarization.objects.all().order_by('name')
|
||||
self.fields['modulation'].queryset = Modulation.objects.all().order_by('name')
|
||||
self.fields['standard'].queryset = Standard.objects.all().order_by('name')
|
||||
|
||||
# Делаем спутник обязательным полем
|
||||
self.fields['id_satellite'].required = True
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
Дополнительная валидация формы.
|
||||
|
||||
Проверяет соотношение между частотой, полосой частот и символьной скоростью.
|
||||
"""
|
||||
cleaned_data = super().clean()
|
||||
frequency = cleaned_data.get('frequency')
|
||||
freq_range = cleaned_data.get('freq_range')
|
||||
bod_velocity = cleaned_data.get('bod_velocity')
|
||||
|
||||
# Проверка что частота больше полосы частот
|
||||
if frequency and freq_range:
|
||||
if freq_range > frequency:
|
||||
self.add_error('freq_range', 'Полоса частот не может быть больше частоты')
|
||||
|
||||
# Проверка что символьная скорость соответствует полосе частот
|
||||
if bod_velocity and freq_range:
|
||||
if bod_velocity > freq_range * 1000000: # Конвертация МГц в Гц
|
||||
self.add_error('bod_velocity', 'Символьная скорость не может превышать полосу частот')
|
||||
|
||||
return cleaned_data
|
||||
|
||||
class GeoForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Geo
|
||||
fields = ['location', 'comment', 'is_average']
|
||||
widgets = {
|
||||
'location': forms.TextInput(attrs={'class': 'form-control'}),
|
||||
'comment': forms.TextInput(attrs={'class': 'form-control'}),
|
||||
'is_average': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
|
||||
}
|
||||
|
||||
class ObjItemForm(forms.ModelForm):
|
||||
"""
|
||||
Форма для создания и редактирования объектов (источников сигнала).
|
||||
|
||||
Работает с моделью ObjItem. Параметры ВЧ загрузки обрабатываются отдельно
|
||||
через ParameterForm с использованием OneToOne связи.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = ObjItem
|
||||
fields = ['name']
|
||||
widgets = {
|
||||
'name': forms.TextInput(attrs={
|
||||
'class': 'form-control',
|
||||
'placeholder': 'Введите название объекта',
|
||||
'maxlength': '100'
|
||||
}),
|
||||
}
|
||||
labels = {
|
||||
'name': 'Название объекта',
|
||||
}
|
||||
help_texts = {
|
||||
'name': 'Уникальное название объекта/источника сигнала',
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
# Делаем поле name необязательным, так как оно может быть пустым
|
||||
self.fields['name'].required = False
|
||||
|
||||
def clean_name(self):
|
||||
"""
|
||||
Валидация поля name.
|
||||
|
||||
Проверяет что название не состоит только из пробелов.
|
||||
"""
|
||||
name = self.cleaned_data.get('name')
|
||||
|
||||
if name:
|
||||
# Удаляем лишние пробелы
|
||||
name = name.strip()
|
||||
|
||||
# Проверяем что после удаления пробелов что-то осталось
|
||||
if not name:
|
||||
raise forms.ValidationError('Название не может состоять только из пробелов')
|
||||
|
||||
return name
|
||||
Reference in New Issue
Block a user