diff --git a/.gitignore b/.gitignore index 8a466f4..aff9bfc 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,5 @@ data.json django-leaflet admin-interface -docker-* \ No newline at end of file +docker-* +maplibre-gl-js-5.10.0.zip \ No newline at end of file diff --git a/dbapp/mainapp/admin.py b/dbapp/mainapp/admin.py index 56198ac..6c9b831 100644 --- a/dbapp/mainapp/admin.py +++ b/dbapp/mainapp/admin.py @@ -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( diff --git a/dbapp/mainapp/forms.py b/dbapp/mainapp/forms.py index edc4943..aef2fce 100644 --- a/dbapp/mainapp/forms.py +++ b/dbapp/mainapp/forms.py @@ -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={ diff --git a/dbapp/mainapp/templates/mainapp/link_vch.html b/dbapp/mainapp/templates/mainapp/link_vch.html index 65de198..3ffdf14 100644 --- a/dbapp/mainapp/templates/mainapp/link_vch.html +++ b/dbapp/mainapp/templates/mainapp/link_vch.html @@ -20,7 +20,7 @@ {% endfor %} {% endif %} -

Введите допустимый разброс для частоты и полосы(в кГц)

+

Введите допустимый разброс для частоты и полосы

{% csrf_token %} @@ -39,7 +39,7 @@ {% endif %} {% endcomment %}
- + {{ form.value1 }} {% if form.value1.errors %}
{{ form.value1.errors }}
diff --git a/dbapp/mainapp/utils.py b/dbapp/mainapp/utils.py index 1e51c4c..7c4513d 100644 --- a/dbapp/mainapp/utils.py +++ b/dbapp/mainapp/utils.py @@ -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()) diff --git a/dbapp/mainapp/views.py b/dbapp/mainapp/views.py index b5ec0d0..4a99cbf 100644 --- a/dbapp/mainapp/views.py +++ b/dbapp/mainapp/views.py @@ -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') diff --git a/dbapp/mapsapp/templates/mapsapp/map2d_base.html b/dbapp/mapsapp/templates/mapsapp/map2d_base.html index 10b893b..3f3bb2b 100644 --- a/dbapp/mapsapp/templates/mapsapp/map2d_base.html +++ b/dbapp/mapsapp/templates/mapsapp/map2d_base.html @@ -53,9 +53,15 @@ const satellite = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { attribution: 'Tiles © 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); diff --git a/dbapp/mapsapp/views.py b/dbapp/mapsapp/views.py index f664b6b..8a82554 100644 --- a/dbapp/mapsapp/views.py +++ b/dbapp/mapsapp/views.py @@ -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 diff --git a/gdal-3.10.2-cp313-cp313-win_amd64.whl b/gdal-3.10.2-cp313-cp313-win_amd64.whl deleted file mode 100644 index 07335c9..0000000 Binary files a/gdal-3.10.2-cp313-cp313-win_amd64.whl and /dev/null differ