diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2023-03-21 22:27:58 +0100 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2023-04-03 12:48:00 +0200 |
commit | a847ded15c80dfa0b16dee5c1ea109da06af7b34 (patch) | |
tree | e981f729ceae0a4444105323ed3ad16b9a7a9bc6 /ishtar_common | |
parent | 05911c88dacbc5dd974fa5697dd08e9ab1d35d1d (diff) | |
download | Ishtar-a847ded15c80dfa0b16dee5c1ea109da06af7b34.tar.bz2 Ishtar-a847ded15c80dfa0b16dee5c1ea109da06af7b34.zip |
Load task refactoring - manage external_id regen with tasks - cascade update from warehouse to containers (refs #5432) - containers manage history
Diffstat (limited to 'ishtar_common')
-rw-r--r-- | ishtar_common/migrations/0201_squashed.py | 6 | ||||
-rw-r--r-- | ishtar_common/models.py | 1 | ||||
-rw-r--r-- | ishtar_common/models_common.py | 91 | ||||
-rw-r--r-- | ishtar_common/utils.py | 98 |
4 files changed, 115 insertions, 81 deletions
diff --git a/ishtar_common/migrations/0201_squashed.py b/ishtar_common/migrations/0201_squashed.py index 08912e1ee..aa5582f9a 100644 --- a/ishtar_common/migrations/0201_squashed.py +++ b/ishtar_common/migrations/0201_squashed.py @@ -207,7 +207,7 @@ class Migration(migrations.Migration): ishtar_common.models.OwnPerms, models.Model, ishtar_common.models.CachedGen, ishtar_common.models_common.FixAssociated, - ishtar_common.models.CascasdeUpdate, ishtar_common.models.ImageContainerModel, ishtar_common.models.ValueGetter, ishtar_common.models.MainItem), + ishtar_common.models.ImageContainerModel, ishtar_common.models.ValueGetter, ishtar_common.models.MainItem), ), migrations.CreateModel( name='DocumentTemplate', @@ -755,7 +755,7 @@ class Migration(migrations.Migration): ishtar_common.models.TemplateItem, models.Model, ishtar_common.models.CachedGen, ishtar_common.models_common.FixAssociated, - ishtar_common.models.CascasdeUpdate, ishtar_common.models.OwnPerms, ishtar_common.models.ValueGetter, ishtar_common.models.MainItem), + ishtar_common.models.OwnPerms, ishtar_common.models.ValueGetter, ishtar_common.models.MainItem), ), migrations.CreateModel( name='OrganizationType', @@ -831,7 +831,7 @@ class Migration(migrations.Migration): ishtar_common.models.TemplateItem, models.Model, ishtar_common.models.CachedGen, ishtar_common.models_common.FixAssociated, - ishtar_common.models.CascasdeUpdate, ishtar_common.models.OwnPerms, ishtar_common.models.ValueGetter, ishtar_common.models.MainItem), + ishtar_common.models.OwnPerms, ishtar_common.models.ValueGetter, ishtar_common.models.MainItem), ), migrations.CreateModel( name='PersonType', diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 420670ca1..c053f7c10 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -164,7 +164,6 @@ from ishtar_common.models_common import ( ImageContainerModel, StatisticItem, CachedGen, - CascasdeUpdate, Department, State, ) diff --git a/ishtar_common/models_common.py b/ishtar_common/models_common.py index 5a27f8ca9..fd12f19be 100644 --- a/ishtar_common/models_common.py +++ b/ishtar_common/models_common.py @@ -69,6 +69,7 @@ from ishtar_common.utils import ( get_all_field_names, merge_tsvectors, cached_label_changed, + external_id_changed, post_save_geo, post_save_geodata, task, @@ -1188,7 +1189,7 @@ class JsonData(models.Model, CachedGen): else: print("To many level in json field - fix not managed") obj.data = data - obj._no_post_process = True + obj.no_post_process() obj.save() multi = True for v in value: @@ -1248,22 +1249,6 @@ class FixAssociated: setattr(item, subkey, new_value) -class CascasdeUpdate: - DOWN_MODEL_UPDATE = [] - - def cascade_update(self): - for down_model in self.DOWN_MODEL_UPDATE: - if not settings.USE_BACKGROUND_TASK: - rel = getattr(self, down_model) - if hasattr(rel.model, "need_update"): - rel.update(need_update=True) - continue - for item in getattr(self, down_model).all(): - cached_label_changed(item.__class__, instance=item) - if hasattr(item, "main_geodata"): - post_save_geo(item.__class__, instance=item) - - class SearchAltName(object): def __init__( self, search_key, search_query, extra_query=None, distinct_query=False @@ -1436,7 +1421,6 @@ class BaseHistorizedItem( Imported, JsonData, FixAssociated, - CascasdeUpdate, ): """ Historized item with external ID management. @@ -1731,12 +1715,6 @@ class BaseHistorizedItem( def save(self, *args, **kwargs): created = not self.pk - if getattr(self, "_no_post_process", False): - self.skip_history_when_saving = True - self._cached_label_checked = True - self._post_saved_geo = True - self._no_move = True - if (not getattr(self, "skip_history_when_saving", False) and not getattr(self, "_no_last_modified_update", False)) \ or not self.last_modified: @@ -4176,7 +4154,7 @@ class CompleteIdentifierItem(models.Model, ImageContainerModel): super(CompleteIdentifierItem, self).save(*args, **kwargs) self.regenerate_all_ids() - def regenerate_all_ids(self): + def regenerate_all_ids(self, save=True): if getattr(self, "_prevent_loop", False): return modified = False @@ -4191,7 +4169,9 @@ class CompleteIdentifierItem(models.Model, ImageContainerModel): if modified: self._prevent_loop = True self.skip_history_when_saving = True - self.save() + if save: + self.save() + return modified class SearchVectorConfig: @@ -4383,10 +4363,54 @@ class MainItem(ShortMenuItem, SerializeItem): """ Item with quick actions available from tables Extra actions are available from sheets + Manage cascade updated, has_changed and no_post_process """ QUICK_ACTIONS = [] SLUG = "" + DOWN_MODEL_UPDATE = [] + INITIAL_VALUES = [] # list of field checkable if changed on save + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._initial_values = {} + for field_name in self.INITIAL_VALUES: + self._initial_values[field_name] = getattr(self, field_name) + + def has_changed(self): + """ + Check which field have a changed value between INITIAL_VALUES + :return: list of changed fields + """ + changed = [] + for field_name in self._initial_values: + value = getattr(self, field_name) + if self._initial_values[field_name] != value: + changed.append(field_name) + self._initial_values[field_name] = value + return changed + + def cascade_update(self, changed=True): + if not changed: + return + for down_model in self.DOWN_MODEL_UPDATE: + if not settings.USE_BACKGROUND_TASK: + rel = getattr(self, down_model) + if hasattr(rel.model, "need_update"): + rel.update(need_update=True) + continue + for item in getattr(self, down_model).all(): + item.cached_label_changed() + if hasattr(item, "main_geodata"): + item.post_save_geo() + + def no_post_process(self): + self.skip_history_when_saving = True + self._cached_label_checked = True + self._post_saved_geo = True + self._external_id_changed = False + self._search_updated = True + self._no_move = True @classmethod def app_label(cls): @@ -4450,6 +4474,21 @@ class MainItem(ShortMenuItem, SerializeItem): self.auto_external_id = True self.save() + def cached_label_changed(self): + self.no_post_process() + self._cached_label_checked = False + cached_label_changed(self.__class__, instance=self, created=False) + + def post_save_geo(self): + self.no_post_process() + self._post_saved_geo = False + post_save_geo(self.__class__, instance=self, created=False) + + def external_id_changed(self): + self.no_post_process() + self._external_id_changed = False + external_id_changed(self.__class__, instance=self, created=False) + def get_extra_actions(self, request): if not hasattr(self, "SLUG"): return [] diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py index 7c7e6a6a5..65b937339 100644 --- a/ishtar_common/utils.py +++ b/ishtar_common/utils.py @@ -503,41 +503,42 @@ def revoke_old_task(kwargs, action_name, task_id, instance_cls): cache.set(key, task_id, settings.CACHE_TIMEOUT * 4) -def cached_label_changed(sender, **kwargs): - if not kwargs.get("instance"): +def load_task(task_func, task_name, checks, sender, **kwargs): + instance = kwargs.get("instance", None) + if not instance: return - instance = kwargs.get("instance") if hasattr(instance, "test_obj"): instance.test_obj.reached(sender, **kwargs) - # cache_key, value = get_cache( - # sender, ["cached_label_changed", kwargs['instance'].pk] - # ) - # if value and not settings.DISABLE_TASK_TIMEOUT: - # # multiple request too quick - # return - # cache.set(cache_key, True, settings.CACHE_TASK_TIMEOUT) + if checks: + for check in checks: + if getattr(instance, check, None): + return if ( - not settings.USE_BACKGROUND_TASK - or not instance.pk - or not sender.objects.filter(pk=instance.pk).count() + not settings.USE_BACKGROUND_TASK + or not instance.pk + or not sender.objects.filter(pk=instance.pk).count() ): # no background task or not yet fully saved - return _cached_label_changed(sender, **kwargs) - + return task_func(sender, **kwargs) if getattr(instance, "_cascade_change", False): kwargs["cascade_change"] = True sender, kwargs = serialize_args_for_tasks( sender, instance, kwargs, EXTRA_KWARGS_TRIGGER ) - task_item = _cached_label_changed.delay(sender, **kwargs) - revoke_old_task(kwargs, "cached_label_changed", task_item.id, instance.__class__) + task_item = task_func.delay(sender, **kwargs) + revoke_old_task(kwargs, task_name, task_item.id, instance.__class__) return task_item +def cached_label_changed(sender, **kwargs): + return load_task(_cached_label_changed, "cached_label_changed", None, sender, + **kwargs) + + @task() def _cached_label_changed(sender, **kwargs): sender, instance = deserialize_args_for_tasks(sender, kwargs, EXTRA_KWARGS_TRIGGER) @@ -613,6 +614,30 @@ def regenerate_all_cached_labels(model): cached_label_changed(model, instance=item) +def external_id_changed(sender, **kwargs): + return load_task(_external_id_changed, "external_id_changed", + ["_external_id_changed"], sender, **kwargs) + + +@task() +def _external_id_changed(sender, **kwargs): + sender, instance = deserialize_args_for_tasks(sender, kwargs, EXTRA_KWARGS_TRIGGER) + if not instance: + return + updated = False + instance.no_post_process() + if not instance.external_id or instance.auto_external_id: + external_id = get_generated_id(instance.SLUG + "_external_id", instance) + if external_id != instance.external_id: + updated = True + instance.auto_external_id = True + instance.external_id = external_id + updated |= instance.regenerate_all_ids(save=False) + if updated: + instance.save() + + + def shortify(lbl, number=20): SHORTIFY_STR = ugettext(" (...)") if not lbl: @@ -749,19 +774,8 @@ def get_srid_obj_from_point(point): def post_save_geodata(sender, **kwargs): - instance = kwargs.get("instance", None) - if not instance: - return - if hasattr(instance, "_no_geo_check") and instance._no_geo_check: - return - if not settings.USE_BACKGROUND_TASK: - return _post_save_geodata(sender, **kwargs) - sender, kwargs = serialize_args_for_tasks( - sender, instance, kwargs, EXTRA_KWARGS_TRIGGER - ) - task_item = _post_save_geodata.delay(sender, **kwargs) - revoke_old_task(kwargs, "post_save_geodata", task_item.id, instance.__class__) - return task_item + return load_task(_post_save_geodata, "post_save_geodata", ["_no_geo_check"], sender, + **kwargs) @task() @@ -817,26 +831,8 @@ def post_save_geo(sender, **kwargs): """ Convert raw x, y, z point to real geo field """ - if not kwargs.get("instance"): - return - # cache_key, value = get_cache( - # sender, ["post_save_geo", kwargs['instance'].pk]) - # if value and not settings.DISABLE_TASK_TIMEOUT: - # # multiple request too quick - # return - # cache.set(cache_key, True, settings.CACHE_TASK_TIMEOUT) - - instance = kwargs.get("instance") - if hasattr(instance, "_no_geo_check") and instance._no_geo_check: - return - if not settings.USE_BACKGROUND_TASK: - return _post_save_geo(sender, **kwargs) - sender, kwargs = serialize_args_for_tasks( - sender, instance, kwargs, EXTRA_KWARGS_TRIGGER - ) - task_item = _post_save_geo.delay(sender, **kwargs) - revoke_old_task(kwargs, "post_save_geo", task_item.id, instance.__class__) - return task_item + return load_task(_post_save_geo, "post_save_geo", ["_no_geo_check"], + sender, **kwargs) @task() @@ -1966,7 +1962,7 @@ def get_generated_id(key, item): profile = get_current_profile() if not hasattr(profile, key): return - formula = getattr(profile, key) + formula = getattr(profile, key, None) if not formula: return "" |