rework objitem model

This commit is contained in:
2025-10-31 12:08:47 +03:00
parent 20a13414de
commit 6df48deb3c
9 changed files with 74 additions and 79 deletions

3
.gitignore vendored
View File

@@ -16,4 +16,5 @@ data.json
django-leaflet
admin-interface
docker-*
docker-*
maplibre-gl-js-5.10.0.zip

View File

@@ -98,6 +98,8 @@ class GeoInline(admin.StackedInline):
verbose_name_plural = "Гео"
form = LocationForm
readonly_fields = ("distance_coords_kup", "distance_coords_valid", "distance_kup_valid")
prefetch_related = ("mirrors",)
autocomplete_fields = ('mirrors',)
fieldsets = (
("Основная информация", {
"fields": ("mirrors", "location", "distance_coords_kup",
@@ -223,7 +225,7 @@ class ParameterAdmin(ImportExportActionModelAdmin, admin.ModelAdmin):
)
ordering = ("frequency",)
list_select_related = ("polarization", "modulation", "standard", "id_satellite",)
filter_horizontal = ('objitems',) # For many-to-many relationship
autocomplete_fields = ('objitems',)
# raw_id_fields = ("id_sigma_parameter", )
inlines = [SigmaParameterInline]
# autocomplete_fields = ("id_sigma_parameter", )
@@ -402,44 +404,17 @@ def show_on_map(modeladmin, request, queryset):
show_on_map.short_description = "Показать выбранные на карте"
class ObjItemForm(forms.ModelForm):
parameter = forms.ModelChoiceField(
queryset=Parameter.objects.all(),
required=False,
label="Параметр"
)
class Meta:
model = ObjItem
fields = '__all__'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Set initial value if the ObjItem already has a parameter
if self.instance.pk:
first_param = self.instance.parameters_obj.first()
if first_param:
self.fields['parameter'].initial = first_param
def save(self, commit=True):
instance = super().save(commit=commit)
# Handle the single parameter assignment - replace all existing relationships
if self.cleaned_data.get('parameter'):
# Clear all existing parameter relationships
instance.parameters_obj.clear()
# Add the selected parameter
instance.parameters_obj.add(self.cleaned_data['parameter'])
else:
# If no parameter selected, clear all
instance.parameters_obj.clear()
return instance
class ParameterObjItemInline(admin.StackedInline):
model = ObjItem.parameters_obj.through
extra = 0
max_num = 1
verbose_name = "ВЧ загрузка"
verbose_name_plural = "ВЧ загрузки"
@admin.register(ObjItem)
class ObjectAdmin(admin.ModelAdmin):
form = ObjItemForm
list_display = (
"name",
"sat_name",
@@ -475,9 +450,11 @@ class ObjectAdmin(admin.ModelAdmin):
)
ordering = ("name",)
inlines = [GeoInline]
inlines = [ParameterObjItemInline, GeoInline]
actions = [show_on_map]
def get_queryset(self, request):
qs = super().get_queryset(request)
return qs.select_related('geo_obj').prefetch_related(

View File

@@ -60,12 +60,12 @@ class VchLinkForm(forms.Form):
'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='Выбор диапазона'
)
# 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={

View File

@@ -20,7 +20,7 @@
{% endfor %}
{% endif %}
<p class="card-text">Введите допустимый разброс для частоты и полосы(в кГц)</p>
<p class="card-text">Введите допустимый разброс для частоты и полосы</p>
<form method="post">
{% csrf_token %}
@@ -39,7 +39,7 @@
{% endif %}
</div> {% endcomment %}
<div class="mb-3">
<label for="{{ form.value1.id_for_label }}" class="form-label">Разброс по частоте(в %)</label>
<label for="{{ form.value1.id_for_label }}" class="form-label">Разброс по частоте(в МГц)</label>
{{ form.value1 }}
{% if form.value1.errors %}
<div class="text-danger mt-1">{{ form.value1.errors }}</div>

View File

@@ -143,19 +143,14 @@ def fill_data_from_df(df: pd.DataFrame, sat: Satellite):
geo_obj=geo
)
if not existing_obj_items.exists():
# Такой объект уже существует, используем его
# obj_item = existing_obj_items.first()
obj_item = ObjItem.objects.create(
name=source,
id_user_add=CustomUser.objects.get(id=1)
)
# Устанавливаем связь с параметром
obj_item.parameters_obj.set([vch_load_obj])
# Устанавливаем связь с geo
geo.objitem = obj_item
geo.save()
# else:
# Создаем новый ObjItem
# obj_item, _ = ObjItem.objects.get_or_create(
@@ -280,16 +275,18 @@ def get_points_from_csv(file_content):
)
geo_obj.mirrors.set(Mirror.objects.filter(name__in=mir_lst))
obj_item_obj, _ = ObjItem.objects.get_or_create(
name=row['obj'],
# id_satellite=sat_obj,
id_vch_load=vch_load_obj,
id_geo=geo_obj,
defaults={
'id_user_add': CustomUser.objects.get(id=1)
}
existing_obj_items = ObjItem.objects.filter(
parameters_obj=vch_load_obj,
geo_obj=geo_obj
)
obj_item_obj.save()
if not existing_obj_items.exists():
obj_item = ObjItem.objects.create(
name=row['obj'],
id_user_add=CustomUser.objects.get(id=1)
)
obj_item.parameters_obj.set([vch_load_obj])
geo_obj.objitem = obj_item
geo_obj.save()
def get_vch_load_from_html(file, sat: Satellite) -> None:
filename = file.name.split('_')
@@ -367,18 +364,17 @@ def get_vch_load_from_html(file, sat: Satellite) -> None:
sigma_load.save()
def compare_and_link_vch_load(sat_id: Satellite, eps_freq: float, eps_frange: float, ku_range: float):
item_obj = ObjItem.objects.filter(id_vch_load__id_satellite=sat_id)
item_obj = ObjItem.objects.filter(parameters_obj__id_satellite=sat_id)
vch_sigma = SigmaParameter.objects.filter(id_satellite=sat_id)
link_count = 0
obj_count = len(item_obj)
for idx, obj in enumerate(item_obj):
vch_load = obj.id_vch_load
vch_load = obj.parameters_obj.get()
if vch_load.frequency == -1.0:
continue
# if unique_points = Point.objects.order_by('frequency').distinct('frequency')
for sigma in vch_sigma:
if (
abs(sigma.transfer_frequency - vch_load.frequency) <= vch_load.frequency*eps_freq/100 and
abs(sigma.transfer_frequency - vch_load.frequency) <= eps_freq and
abs(sigma.freq_range - vch_load.freq_range) <= vch_load.freq_range*eps_frange/100 and
sigma.polarization == vch_load.polarization
):
@@ -395,11 +391,18 @@ def kub_report(data_in: io.StringIO) -> pd.DataFrame:
for row in df_in.iterrows():
value = row[1]
date = datetime.date(datetime.now())
lat = value['Широта, град']
lon = value['Долгота, град']
isz = value['ИСЗ']
downlink = value['Обратный канал, МГц']
freq_range = value['Полоса, МГц']
try:
lat = float(value['Широта, град'].strip().replace(',', '.'))
lon = float(value['Долгота, град'].strip().replace(',', '.'))
downlink = float(value['Обратный канал, МГц'].strip().replace(',', '.'))
freq_range = float(value['Полоса, МГц'].strip().replace(',', '.'))
except Exception as e:
lat = value['Широта, град']
lon = value['Долгота, град']
downlink = value['Обратный канал, МГц']
freq_range = value['Полоса, МГц']
print(e)
norad = int(re.findall(r'\((\d+)\)', isz)[0])
sat_obj = Satellite.objects.get(norad=norad)
pol_obj = Polarization.objects.get(name=value['Поляризация'].strip())

View File

@@ -92,23 +92,24 @@ from django.views.generic import View
class GetLocationsView(View):
def get(self, request, sat_id):
locations = ObjItem.objects.filter(id_vch_load__id_satellite=sat_id)
locations = ObjItem.objects.filter(parameters_obj__id_satellite=sat_id)
if not locations:
return JsonResponse({'error': 'Объектов не найдено'}, status=400)
features = []
for loc in locations:
param = loc.parameters_obj.get()
features.append({
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [loc.id_geo.coords[0], loc.id_geo.coords[1]]
"coordinates": [loc.geo_obj.coords[0], loc.geo_obj.coords[1]]
},
"properties": {
"pol": loc.id_vch_load.polarization.name,
"freq": loc.id_vch_load.frequency*1000000,
"pol": param.polarization.name,
"freq": param.frequency*1000000,
"name": f"{loc.name}",
"id": loc.id_geo.id
"id": loc.geo_obj.id
}
})
@@ -153,12 +154,19 @@ class ShowMapView(UserPassesTestMixin, View):
points = []
if ids:
id_list = [int(x) for x in ids.split(',') if x.isdigit()]
locations = ObjItem.objects.filter(id__in=id_list)
locations = ObjItem.objects.filter(id__in=id_list).prefetch_related(
'parameters_obj__id_satellite',
'parameters_obj__polarization',
'parameters_obj__modulation',
'parameters_obj__standard',
'geo_obj'
)
for obj in locations:
param = obj.parameters_obj.get()
points.append({
'name': f"{obj.name}",
'freq': f"{obj.id_vch_load.frequency} [{obj.id_vch_load.freq_range}] МГц",
'point': (obj.id_geo.coords.x, obj.id_geo.coords.y)
'freq': f"{param.frequency} [{param.freq_range}] МГц",
'point': (obj.geo_obj.coords.x, obj.geo_obj.coords.y)
})
else:
return redirect('admin')
@@ -222,10 +230,10 @@ class LinkVchSigmaView(FormView):
def form_valid(self, form):
freq = form.cleaned_data['value1']
freq_range = form.cleaned_data['value2']
ku_range = float(form.cleaned_data['ku_range'])
# ku_range = float(form.cleaned_data['ku_range'])
sat_id = form.cleaned_data['sat_choice']
# print(freq, freq_range, ku_range, sat_id.pk)
count_all, link_count = compare_and_link_vch_load(sat_id, freq, freq_range, ku_range)
count_all, link_count = compare_and_link_vch_load(sat_id, freq, freq_range, 1)
messages.success(self.request, f"Привязано {link_count} из {count_all} объектов")
return redirect('link_vch_sigma')

View File

@@ -53,9 +53,15 @@
const satellite = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
attribution: 'Tiles &copy; Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
});
const street_local = L.tileLayer('http://127.0.0.1:8080/styles/basic-preview/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: 'Local Tiles'
});
street_local.addTo(map);
const baseLayers = {
"Улицы": street,
"Спутник": satellite
"Спутник": satellite,
"Локально": street_local
};
L.control.layers(baseLayers).addTo(map);
map.setMaxZoom(18);

View File

@@ -72,7 +72,7 @@ class GetTransponderOnSatIdView(View):
output.append(
{
"name": tran.name,
"frequency": tran.frequency,
"frequency": tran.downlink,
"frequency_range": tran.frequency_range,
"zone_name": tran.zone_name,
"polarization": tran.polarization.name