From d6e79554718fb618425b3c7085427d170ecf79f0 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sun, 22 Sep 2024 10:51:51 +0200 Subject: ✨ imports: manage post processing of linked items - post importer for Parcel: set_parcel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- archaeological_operations/models.py | 18 ++++++++++++++++++ ishtar_common/data_importer.py | 29 ++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py index f4430a8f1..f8c8f20a0 100644 --- a/archaeological_operations/models.py +++ b/archaeological_operations/models.py @@ -20,6 +20,7 @@ from collections import OrderedDict import datetime from itertools import groupby +import re import uuid from django.apps import apps @@ -34,6 +35,7 @@ from django.db.models import Q, Count, Sum, Max, Avg from django.db.models.signals import post_save, m2m_changed, post_delete from django.forms import ValidationError from django.urls import reverse +from ishtar_common.data_importer import post_importer_action from ishtar_common.utils import ugettext_lazy as _, pgettext_lazy, get_generated_id from ishtar_common.models import ( @@ -3345,6 +3347,22 @@ class Parcel(LightHistorizedItem): def __str__(self): return self.short_label + @post_importer_action + def set_parcel(self, __, value): + """ + Set section and parcel number from a string + """ + RE_PARCEL = re.compile(r"([A-Za-z]{1,4})(\d+)") + m = RE_PARCEL.match(value) + if not m: + return + self.section, self.parcel_number = m.groups() + self.__class__.objects.filter(pk=self.pk).update( + section=self.section, parcel_number=self.parcel_number + ) + + set_parcel.post_save = True + def natural_key(self): return (self.uuid,) diff --git a/ishtar_common/data_importer.py b/ishtar_common/data_importer.py index 4285a658b..7717c0e03 100644 --- a/ishtar_common/data_importer.py +++ b/ishtar_common/data_importer.py @@ -32,7 +32,7 @@ from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType from django.contrib.gis.geos.error import GEOSException from django.db.models.fields import FieldDoesNotExist -from django.core.exceptions import FieldError +from django.core.exceptions import FieldError, MultipleObjectsReturned from django.core.files import File from django.db import IntegrityError, DatabaseError, transaction from django.db.models import Q @@ -881,10 +881,29 @@ class Importer(object): def post_processing(self, idx_line, item): # force django based post-processing for the item item = item.__class__.objects.get(pk=item.pk) - for func, context, value in self._item_post_processing: + for cls, func, context, value in self._item_post_processing: context["import_object"] = self.import_instance + if cls != item.__class__: + # try to get associated item + current_item = None + for id_key in ("id", "pk", "external_id"): + if context.get(id_key, None): + try: + current_item = cls.objects.get(**{id_key: context[id_key]}) + except (cls.DoesNotExist, MultipleObjectsReturned) as __: + break + if not current_item: + self.errors.append( + (idx_line, None, + str(_("Item {} with values: {} not identified for post-treatment - need a non ambiguous key")).format( + cls.__name__, str(context) + )) + ) + continue + else: + current_item = item try: - f = getattr(item, func) + f = getattr(current_item, func) returned = f(context, value) if returned and not getattr(f, "_no_repost_save", False): if not isinstance(returned, Iterable): @@ -1215,7 +1234,7 @@ class Importer(object): self._throughs = [] # list of (formater, value) self._post_processing = [] # list of (formater, value) - self._item_post_processing = [] + self._item_post_processing = [] # cls, attribute, data, value data = {} self.current_csv_line = None @@ -1811,7 +1830,7 @@ class Importer(object): if func.importer_trigger == "pre": func(data, data[attribute]) elif func.importer_trigger == "post": - self._item_post_processing.append([attribute, data, data[attribute]]) + self._item_post_processing.append([cls, attribute, data, data[attribute]]) else: logger.warning( "Unknow importer_trigger '{}' for '{}'".format( -- cgit v1.2.3