summaryrefslogtreecommitdiff
path: root/ishtar_common
diff options
context:
space:
mode:
Diffstat (limited to 'ishtar_common')
-rw-r--r--ishtar_common/migrations/0201_squashed.py6
-rw-r--r--ishtar_common/models.py1
-rw-r--r--ishtar_common/models_common.py91
-rw-r--r--ishtar_common/utils.py98
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 ""