diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2020-10-07 19:09:30 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2021-02-28 12:15:21 +0100 |
commit | 9d5f0791187ff6b18d3ffa4db4d593fe96834e8d (patch) | |
tree | 9cd21bf7e51d271b958a9a4b2b85367adbb97992 /ishtar_common/utils.py | |
parent | e5c0a159929fc64d63db37ebd85a5a810faf2534 (diff) | |
download | Ishtar-9d5f0791187ff6b18d3ffa4db4d593fe96834e8d.tar.bz2 Ishtar-9d5f0791187ff6b18d3ffa4db4d593fe96834e8d.zip |
Refactoring of models. Document container - declare only id
Diffstat (limited to 'ishtar_common/utils.py')
-rw-r--r-- | ishtar_common/utils.py | 118 |
1 files changed, 114 insertions, 4 deletions
diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py index 41a844026..31459f861 100644 --- a/ishtar_common/utils.py +++ b/ishtar_common/utils.py @@ -37,6 +37,7 @@ import subprocess import sys import tempfile import time +import uuid import xmltodict import zipfile @@ -48,7 +49,7 @@ from django.contrib.contenttypes.models import ContentType from django.contrib.gis.geos import GEOSGeometry from django.contrib.sessions.backends.db import SessionStore from django.core.cache import cache -from django.core.exceptions import SuspiciousOperation +from django.core.exceptions import SuspiciousOperation, ObjectDoesNotExist from django.core.files import File from django.core.validators import EMPTY_VALUES from django.core.urlresolvers import reverse @@ -713,9 +714,6 @@ def _post_save_geo(sender, **kwargs): """ Convert raw x, y, z point to real geo field """ - from ishtar_common.models import get_current_profile # not clean but utils - # is loaded before models - profile = get_current_profile() if not profile.mapping: return @@ -1758,3 +1756,115 @@ def try_fix_file(filename, make_copy=True, hard=False): if make_copy: shutil.copy2(full_file, filename) return f + + +def get_current_profile(force=False): + IshtarSiteProfile = apps.get_model("ishtar_common", "IshtarSiteProfile") + return IshtarSiteProfile.get_current_profile(force=force) + + +PARSE_FORMULA = re.compile("{([^}]*)}") + + +def _deduplicate(value): + new_values = [] + for v in value.split('-'): + if v not in new_values: + new_values.append(v) + return '-'.join(new_values) + + +FORMULA_FILTERS = { + 'upper': lambda x: x.upper(), + 'lower': lambda x: x.lower(), + 'capitalize': lambda x: x.capitalize(), + 'slug': lambda x: slugify(x), + 'deduplicate': _deduplicate +} + + +def get_external_id(key, item): + profile = get_current_profile() + if not hasattr(profile, key): + return + formula = getattr(profile, key) + dct = {} + for fkey in PARSE_FORMULA.findall(formula): + filtered = fkey.split('|') + initial_key = fkey[:] + fkey = filtered[0] + filters = [] + for filtr in filtered[1:]: + if filtr in FORMULA_FILTERS: + filters.append(FORMULA_FILTERS[filtr]) + if fkey.startswith('settings__'): + dct[fkey] = getattr(settings, fkey[len('settings__'):]) or '' + continue + obj = item + for k in fkey.split('__'): + try: + obj = getattr(obj, k) + except ObjectDoesNotExist: + obj = None + if hasattr(obj, 'all') and hasattr(obj, 'count'): # query manager + if not obj.count(): + break + obj = obj.all()[0] + elif callable(obj): + obj = obj() + if obj is None: + break + if obj is None: + dct[initial_key] = '' + else: + dct[initial_key] = str(obj) + for filtr in filters: + dct[initial_key] = filtr(dct[initial_key]) + values = formula.format(**dct).split('||') + value = values[0] + for filtr in values[1:]: + if filtr not in FORMULA_FILTERS: + value += '||' + filtr + continue + value = FORMULA_FILTERS[filtr](value) + return value + + +PRIVATE_FIELDS = ('id', 'history_modifier', 'order', 'uuid') + + +def duplicate_item(item, user=None, data=None): + model = item.__class__ + new = model.objects.get(pk=item.pk) + + for field in model._meta.fields: + # pk is in PRIVATE_FIELDS so: new.pk = None and a new + # item will be created on save + if field.name == "uuid": + new.uuid = uuid.uuid4() + elif field.name in PRIVATE_FIELDS: + setattr(new, field.name, None) + if user: + new.history_user = user + if data: + for k in data: + setattr(new, k, data[k]) + new.save() + + # m2m fields + m2m = [field.name for field in model._meta.many_to_many + if field.name not in PRIVATE_FIELDS] + for field in m2m: + for val in getattr(item, field).all(): + if val not in getattr(new, field).all(): + getattr(new, field).add(val) + return new + + +def get_image_path(instance, filename): + # when using migrations instance is not a real ImageModel instance + if not hasattr(instance, '_get_image_path'): + n = datetime.datetime.now() + return "upload/{}/{:02d}/{:02d}/{}".format( + n.year, n.month, n.day, filename) + return instance._get_image_path(filename) |