100 lines
3.7 KiB
Python
100 lines
3.7 KiB
Python
"""
|
||
Скрипт для исправления ObjItems без связи с Source.
|
||
|
||
Для каждого ObjItem без source:
|
||
1. Получить координаты из geo_obj
|
||
2. Найти ближайший Source (по coords_average)
|
||
3. Если расстояние <= 0.5 градуса, связать ObjItem с этим Source
|
||
4. Иначе создать новый Source с coords_average = координаты geo_obj
|
||
"""
|
||
|
||
import os
|
||
import django
|
||
|
||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dbapp.settings")
|
||
django.setup()
|
||
|
||
from mainapp.models import ObjItem, Source, CustomUser
|
||
from django.contrib.gis.geos import Point
|
||
from django.contrib.gis.measure import D
|
||
from django.contrib.gis.db.models.functions import Distance
|
||
|
||
|
||
def calculate_distance_degrees(coord1, coord2):
|
||
"""Вычисляет расстояние между двумя координатами в градусах."""
|
||
import math
|
||
|
||
lon1, lat1 = coord1
|
||
lon2, lat2 = coord2
|
||
|
||
return math.sqrt((lon2 - lon1) ** 2 + (lat2 - lat1) ** 2)
|
||
|
||
|
||
def fix_objitems_without_source():
|
||
"""Исправляет ObjItems без связи с Source."""
|
||
|
||
# Получаем пользователя по умолчанию
|
||
default_user = CustomUser.objects.get(id=1)
|
||
|
||
# Получаем все ObjItems без source
|
||
objitems_without_source = ObjItem.objects.filter(source__isnull=True)
|
||
total_count = objitems_without_source.count()
|
||
|
||
print(f"Найдено {total_count} ObjItems без source")
|
||
|
||
if total_count == 0:
|
||
print("Нечего исправлять!")
|
||
return
|
||
|
||
fixed_count = 0
|
||
new_sources_count = 0
|
||
|
||
for objitem in objitems_without_source:
|
||
# Проверяем, есть ли geo_obj
|
||
if not hasattr(objitem, 'geo_obj') or not objitem.geo_obj or not objitem.geo_obj.coords:
|
||
print(f"ObjItem {objitem.id} не имеет geo_obj или координат, пропускаем")
|
||
continue
|
||
|
||
geo_coords = objitem.geo_obj.coords
|
||
coord_tuple = (geo_coords.x, geo_coords.y)
|
||
|
||
# Ищем ближайший Source
|
||
sources_with_coords = Source.objects.filter(coords_average__isnull=False)
|
||
|
||
closest_source = None
|
||
min_distance = float('inf')
|
||
|
||
for source in sources_with_coords:
|
||
source_coord = (source.coords_average.x, source.coords_average.y)
|
||
distance = calculate_distance_degrees(coord_tuple, source_coord)
|
||
|
||
if distance < min_distance:
|
||
min_distance = distance
|
||
closest_source = source
|
||
|
||
# Если нашли близкий Source (расстояние <= 0.5 градуса)
|
||
if closest_source and min_distance <= 0.5:
|
||
objitem.source = closest_source
|
||
objitem.save()
|
||
print(f"ObjItem {objitem.id} связан с Source {closest_source.id} (расстояние: {min_distance:.4f}°)")
|
||
fixed_count += 1
|
||
else:
|
||
# Создаем новый Source
|
||
new_source = Source.objects.create(
|
||
coords_average=Point(coord_tuple, srid=4326),
|
||
created_by=default_user
|
||
)
|
||
objitem.source = new_source
|
||
objitem.save()
|
||
print(f"ObjItem {objitem.id} связан с новым Source {new_source.id}")
|
||
fixed_count += 1
|
||
new_sources_count += 1
|
||
|
||
print(f"\nГотово!")
|
||
print(f"Исправлено ObjItems: {fixed_count}")
|
||
print(f"Создано новых Source: {new_sources_count}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
fix_objitems_without_source()
|