summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archaeological_context_records/models.py34
-rw-r--r--archaeological_operations/models.py2
-rw-r--r--archaeological_warehouse/models.py133
-rw-r--r--ishtar_common/management/commands/ishtar_maintenance.py39
-rw-r--r--ishtar_common/models_common.py5
-rw-r--r--ishtar_common/utils.py6
6 files changed, 121 insertions, 98 deletions
diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py
index a14605a5f..0c63ed8e9 100644
--- a/archaeological_context_records/models.py
+++ b/archaeological_context_records/models.py
@@ -389,7 +389,7 @@ class GeographicSubTownItem(GeoItem):
def post_save_geo(self, save=True):
# manage geodata towns
- if getattr(self, "_post_save_geo_ok", False):
+ if getattr(self, "_post_save_geo_ok", False) or not self.pk:
# prevent infinite loop - should not happen, but...
return
self._post_save_geo_ok = True
@@ -414,15 +414,31 @@ class GeographicSubTownItem(GeoItem):
self.main_geodata = None
modified = True
+ current_model = self.__class__
+ main_item_is_set = current_model.objects.filter(
+ id=self.pk,
+ main_geodata__source_content_type__app_label=current_model._meta.app_label,
+ main_geodata__source_content_type__model=current_model._meta.model_name,
+ ).count() # main geo is set for the current model
+
for upper_attr in self.UPPER_GEO:
- upper = getattr(self, upper_attr, None)
- if upper and upper.main_geodata and \
- upper.main_geodata_id not in self.geodata.values_list(
- "id", flat=True):
- modified = True
- self.geodata.add(upper.main_geodata)
- if not self.main_geodata:
- self.main_geodata = upper.main_geodata
+ q_dict = {"id": self.pk, f"{upper_attr}__main_geodata_id__isnull": False}
+ q = current_model.objects.filter(**q_dict)
+ if q.count():
+ upper = None
+ main_geodata_id = q.values_list(f"{upper_attr}__main_geodata_id", flat=True)[0]
+ if main_geodata_id not in self.geodata.values_list("id", flat=True):
+ upper = getattr(self, upper_attr, None)
+ modified = True
+ self.geodata.add(upper.main_geodata)
+
+ if not main_item_is_set:
+ if self.main_geodata_id != main_geodata_id:
+ if not upper:
+ upper = getattr(self, upper_attr, None)
+ modified = True
+ self.main_geodata = upper.main_geodata
+ main_item_is_set = True
if modified and save:
if settings.USE_BACKGROUND_TASK and hasattr(self, "no_post_process"):
diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py
index 6e6bfa53c..8fbba74be 100644
--- a/archaeological_operations/models.py
+++ b/archaeological_operations/models.py
@@ -271,6 +271,8 @@ class GeographicTownItem(GeoItem):
pass
if changed and save:
+ self.no_post_process()
+ self.save()
post_save_geo(self.__class__, instance=self, created=False,
update_fields=False, raw=False, using="default")
return changed
diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py
index 826f4444f..5df824d8f 100644
--- a/archaeological_warehouse/models.py
+++ b/archaeological_warehouse/models.py
@@ -22,7 +22,6 @@ import datetime
import logging
import uuid
-from django.conf import settings
from django.contrib.gis.db import models
from django.contrib.postgres.indexes import GinIndex
from django.core.exceptions import ObjectDoesNotExist
@@ -272,6 +271,51 @@ post_delete.connect(post_save_cache, sender=WarehouseType)
NO_DIVISION_ERROR = _("The division number {} has not been set for the warehouse {}.")
+def warehouse_post_save_geo(item, q_check_town, save=True):
+ # manage geodata towns
+ if getattr(item, "_post_save_geo_ok", False):
+ # prevent infinite loop - should not happen, but...
+ return
+ item._post_save_geo_ok = True
+ if not q_check_town.count():
+ town_id = None
+ q_geotown = GeoVectorData.objects.filter(pk=None)
+ else:
+ town_id = q_check_town.values_list("precise_town_id", flat=True)[0]
+ q_geotown = GeoVectorData.objects.filter(
+ source_content_type__model="town",
+ source_content_type__app_label="ishtar_common",
+ source_id=town_id,
+ multi_polygon__isnull=False)
+ q_geodata_town = item.geodata.filter(
+ source_content_type__model="town",
+ source_content_type__app_label="ishtar_common",
+ )
+ changed = False
+ if not q_geotown.count():
+ # no simple town - clean
+ for geo in q_geodata_town.all():
+ item.geodata.remove(geo)
+ if item.main_geodata == geo:
+ item.main_geodata = None
+ changed = True
+ else:
+ for geo in q_geodata_town.exclude(source_id=town_id).all():
+ item.geodata.remove(geo)
+ if item.main_geodata == geo:
+ item.main_geodata = None
+ changed = True
+ if not q_geodata_town.filter(source_id=town_id).count():
+ item.geodata.add(q_geotown.all()[0])
+ changed = True
+
+ if changed and save:
+ item.skip_history_when_saving = True
+ item._no_move = True
+ item.save()
+ return changed
+
+
class Warehouse(
Address,
DocumentItem,
@@ -427,47 +471,8 @@ class Warehouse(
return self.name
def post_save_geo(self, save=True):
- # manage geodata towns
- if getattr(self, "_post_save_geo_ok", False):
- # prevent infinite loop - should not happen, but...
- return
- self._post_save_geo_ok = True
- if not self.precise_town:
- q_geotown = GeoVectorData.objects.filter(pk=None)
- else:
- q_geotown = GeoVectorData.objects.filter(
- source_content_type__model="town",
- source_content_type__app_label="ishtar_common",
- source_id=self.precise_town.pk,
- multi_polygon__isnull=False)
- q_geodata_town = self.geodata.filter(
- source_content_type__model="town",
- source_content_type__app_label="ishtar_common",
- )
- changed = False
- if not q_geotown.count():
- # no simple town - clean
- for geo in q_geodata_town.all():
- self.geodata.remove(geo)
- if self.main_geodata == geo:
- self.main_geodata = None
- changed = True
- else:
- current_geo_town = q_geotown.all()[0]
- for geo in q_geodata_town.exclude(pk=current_geo_town.pk).all():
- self.geodata.remove(geo)
- if self.main_geodata == geo:
- self.main_geodata = None
- changed = True
- if not q_geodata_town.filter(pk=current_geo_town.pk).count():
- self.geodata.add(current_geo_town)
- changed = True
-
- if changed and save:
- self.skip_history_when_saving = True
- self._no_move = True
- self.save()
- return changed
+ q_check_town = Warehouse.objects.filter(pk=self.pk, precise_town_id__isnull=False)
+ return warehouse_post_save_geo(self, q_check_town, save=save)
def get_container_type_by_place(self, place: int):
"""
@@ -1227,48 +1232,8 @@ class Container(
return self.cached_label or ""
def post_save_geo(self, save=True):
- # manage geodata towns
- if getattr(self, "_post_save_geo_ok", False):
- # prevent infinite loop - should not happen, but...
- return
- self._post_save_geo_ok = True
-
- if not self.location.precise_town:
- town_id = None
- q_geotown = GeoVectorData.objects.filter(pk=None)
- else:
- town_id = self.location.precise_town_id
- q_geotown = GeoVectorData.objects.filter(
- source_content_type__model="town",
- source_content_type__app_label="ishtar_common",
- source_id=self.location.precise_town_id,
- multi_polygon__isnull=False)
- q_geodata_town = self.geodata.filter(
- source_content_type__model="town",
- source_content_type__app_label="ishtar_common",
- )
- changed = False
- if not q_geotown.count():
- for geo in q_geodata_town.all():
- self.geodata.remove(geo)
- if self.main_geodata == geo:
- self.main_geodata = None
- changed = True
- else:
- for geo in q_geodata_town.exclude(source_id=town_id).all():
- self.geodata.remove(geo)
- if self.main_geodata == geo:
- self.main_geodata = None
- changed = True
- if not q_geodata_town.filter(source_id=town_id).count():
- self.geodata.add(q_geotown.all()[0])
- changed = True
-
- if changed and save:
- self.skip_history_when_saving = True
- self._no_move = True
- self.save()
- return changed
+ q_check_town = Warehouse.objects.filter(pk=self.location_id, precise_town_id__isnull=False)
+ return warehouse_post_save_geo(self, q_check_town, save=save)
@property
def start_division_number(self):
diff --git a/ishtar_common/management/commands/ishtar_maintenance.py b/ishtar_common/management/commands/ishtar_maintenance.py
index e4943ea8d..106575570 100644
--- a/ishtar_common/management/commands/ishtar_maintenance.py
+++ b/ishtar_common/management/commands/ishtar_maintenance.py
@@ -18,7 +18,7 @@ from django.core.management.base import BaseCommand, CommandError
from django.template.defaultfilters import slugify
from ishtar_common import models_common
-from ishtar_common.utils import create_default_areas
+from ishtar_common.utils import create_default_areas, BColors
APPS = (
"ishtar_common",
@@ -184,6 +184,33 @@ def _end_task(changed_nb, msg, quiet, store_results, log, log_name, csv_cols):
sys.stdout.write(f"log: {path} written.\n")
+def task_fix_geographic_items(options):
+ quiet = options.get("quiet", False)
+ filtr = options.get("filter", "")
+ model_filter = options.get('model', "").lower()
+ for model in apps.get_models():
+ if not issubclass(model, models_common.GeographicItem) or not hasattr(model, "post_save_geo"):
+ continue
+ if model_filter and model_filter not in (model.__name__.lower(), model._meta.model_name.lower()):
+ continue
+ q = model.objects.exclude(
+ main_geodata__source_content_type__app_label=model._meta.app_label,
+ main_geodata__source_content_type__model=model._meta.model_name,
+ ) # main geo is set for the current model -> do not change
+ if filtr:
+ q = q.filter(**filtr)
+ nb = q.count()
+ total = 0
+ for idx, item in enumerate(q.all()):
+ if not quiet:
+ msg = BColors.format("OKBLUE", f"\r→ {model.__name__}: {idx + 1}/{nb}" + " " * 20)
+ sys.stdout.write(msg)
+ total += 1 if item.post_save_geo() else 0
+ if not quiet:
+ msg = BColors.format("OKGREEN", f"\n* {total} geographic(s) item(s) fixed for {model.__name__}\n")
+ sys.stdout.write(msg)
+
+
def task_main_image(options):
quiet = options.get("quiet", False)
filtr = options.get("filter", "")
@@ -300,6 +327,10 @@ TASKS = {
"help": "create default areas from department and states",
"action": task_default_areas,
},
+ "fix_geographic_items": {
+ "help": "check and fix geographic association and main geographic iem",
+ "action": task_fix_geographic_items,
+ },
"fix_main_image": {
"help": "for items with images and no main image, put the first one created as a main image",
"action": task_main_image,
@@ -393,11 +424,13 @@ class Command(BaseCommand):
quiet = options["quiet"]
if not quiet:
- sys.stdout.write(f"[{get_time()}] Processing task {options['task']}\n")
+ msg = BColors.format("HEADER", f"[{get_time()}] Processing task {options['task']}\n")
+ sys.stdout.write(msg)
errors = TASKS[options["task"]]["action"](options)
if not errors:
if not quiet:
- sys.stdout.write(f"\n[{get_time()}] Task {options['task']} finished\n")
+ msg = BColors.format("HEADER", f"[{get_time()}] Task {options['task']} finished\n")
+ sys.stdout.write(msg)
if options["test"]:
return
sys.exit()
diff --git a/ishtar_common/models_common.py b/ishtar_common/models_common.py
index 9c081a022..ddf5d46d5 100644
--- a/ishtar_common/models_common.py
+++ b/ishtar_common/models_common.py
@@ -3302,9 +3302,10 @@ class MainItem(ShortMenuItem, SerializeItem, SheetItem):
self._cached_label_checked = False
cached_label_changed(self.__class__, instance=self, created=False)
- def post_save_geo(self):
+ def post_save_geo(self, save=True):
+ if getattr(self, "_post_saved_geo", False):
+ return
self.no_post_process()
- self._post_saved_geo = False
post_save_geo(self.__class__, instance=self, created=False)
return False
diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py
index dd21bec06..f734a9b2d 100644
--- a/ishtar_common/utils.py
+++ b/ishtar_common/utils.py
@@ -151,6 +151,12 @@ class BColors:
BOLD = "\033[1m"
UNDERLINE = "\033[4m"
+ @classmethod
+ def format(cls, color, value):
+ if not hasattr(cls, color):
+ return value
+ return f"{getattr(cls, color)}{value}{cls.ENDC}"
+
class Round(models.Func):
function = "ROUND"