diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2019-03-20 11:16:50 +0100 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2019-03-20 11:16:50 +0100 |
commit | 0ea89f12deae7c59b0f5901662c6a519a8f1e017 (patch) | |
tree | 348545788363e80b70d18856d28182242b82e9aa | |
parent | ac80884a42b5fd6032dff409346387616287abd5 (diff) | |
download | Ishtar-0ea89f12deae7c59b0f5901662c6a519a8f1e017.tar.bz2 Ishtar-0ea89f12deae7c59b0f5901662c6a519a8f1e017.zip |
Cache dynamic choices
-rw-r--r-- | ishtar_common/forms.py | 34 | ||||
-rw-r--r-- | ishtar_common/models.py | 55 | ||||
-rw-r--r-- | ishtar_common/utils.py | 3 |
3 files changed, 69 insertions, 23 deletions
diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py index 83b0b2b69..8d0d80497 100644 --- a/ishtar_common/forms.py +++ b/ishtar_common/forms.py @@ -26,9 +26,9 @@ import re import types from django import forms +from django.apps import apps from django.conf import settings from django.contrib.auth.models import User -from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError from django.core.urlresolvers import reverse from django.core import validators @@ -258,18 +258,8 @@ class CustomForm(BSForm): if app_name == "archaeological_files_pdl": app_name = "archaeological_files" model_name = cls.form_slug.split("-")[0].replace('_', "") - ct = ContentType.objects.get(app_label=app_name, model=model_name) - ct_class = ct.model_class() - choices = set() - splitted_key = key[len('data__'):].split('__') - for obj in ct_class.objects.filter( - data__has_key=key[len('data__'):]).all(): - value = obj.data - for k in splitted_key: - value = value[k] - choices.add(value) - choices = [('', '')] + [(v, v) for v in sorted(list(choices))] - return choices + ct_class = apps.get_model(app_name, model_name) + return ct_class._get_dynamic_choices(key) @classmethod def _get_json_fields(cls, custom_form): @@ -279,16 +269,18 @@ class CustomForm(BSForm): :return: ((order1, key1, field1), ...) """ fields = [] - for field in custom_form.json_fields.order_by('order').all(): - key = "data__" + field.json_field.key + for field in custom_form.json_fields.values( + "order", "label", "json_field__name", "json_field__value_type", + "help_text", "json_field__key").order_by('order').all(): + key = "data__" + field["json_field__key"] field_cls, widget = forms.CharField, None - if field.json_field.value_type in JSON_VALUE_TYPES_FIELDS: + if field["json_field__value_type"] in JSON_VALUE_TYPES_FIELDS: field_cls, widget = JSON_VALUE_TYPES_FIELDS[ - field.json_field.value_type] - attrs = {'label': field.label or field.json_field.name, + field["json_field__value_type"]] + attrs = {'label': field["label"] or field["json_field__name"], 'required': False} - if field.help_text: - attrs['help_text'] = field.help_text + if field["help_text"]: + attrs['help_text'] = field["help_text"] if widget: attrs['widget'] = widget() if field_cls == widgets.Select2DynamicField: @@ -299,7 +291,7 @@ class CustomForm(BSForm): kls = f.widget.attrs['class'] + " " + kls f.widget.attrs['class'] = kls f.alt_name = slugify(attrs['label']) - fields.append((field.order or 1, key, f)) + fields.append((field["order"] or 1, key, f)) return fields @classmethod diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 98998eb1f..96dfa716c 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -447,7 +447,22 @@ class OwnPerms(object): return q -class Cached(object): +class CachedGen(object): + @classmethod + def refresh_cache(cls): + raise NotImplementedError() + + @classmethod + def _add_cache_key_to_refresh(cls, keys): + cache_ckey, current_keys = get_cache(cls, ['_current_keys']) + if type(current_keys) != list: + current_keys = [] + if keys not in current_keys: + current_keys.append(keys) + cache.set(cache_ckey, current_keys, settings.CACHE_TIMEOUT) + + +class Cached(CachedGen): slug_field = 'txt_idx' @classmethod @@ -1187,7 +1202,7 @@ class JsonDataField(models.Model): _(u"Content types of the field and of the menu do not match")) -class JsonData(models.Model): +class JsonData(models.Model, CachedGen): data = JSONField(default={}, db_index=True, blank=True) class Meta: @@ -1233,6 +1248,42 @@ class JsonData(models.Model): sections[-1][1].append((field.name, value)) return sections + @classmethod + def refresh_cache(cls): + __, refreshed = get_cache(cls, ['cache_refreshed']) + if refreshed and time.time() - refreshed < 1: + return + cache_ckey, current_keys = get_cache(cls, ['_current_keys']) + if not current_keys: + return + for keys in current_keys: + if keys[0] == '__get_dynamic_choices': + cls._get_dynamic_choices(keys[1], force=True) + + @classmethod + def _get_dynamic_choices(cls, key, force=False): + """ + Get choice from existing values + :param key: data key + :param force: if set to True do not use cache + :return: tuple of choices (id, value) + """ + cache_key, value = get_cache(cls, ['__get_dynamic_choices', key]) + if not force and value: + return value + choices = set() + splitted_key = key[len('data__'):].split('__') + for obj in cls.objects.filter( + data__has_key=key[len('data__'):]).values("data").all(): + value = obj['data'] + for k in splitted_key: + value = value[k] + choices.add(value) + choices = [('', '')] + [(v, v) for v in sorted(list(choices))] + cache.set(cache_key, choices, settings.CACHE_SMALLTIMEOUT) + return choices + + class Imported(models.Model): imports = models.ManyToManyField( diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py index 1d44026e0..55e3a3a75 100644 --- a/ishtar_common/utils.py +++ b/ishtar_common/utils.py @@ -309,6 +309,9 @@ def cached_label_changed(sender, **kwargs): if not force_update and hasattr(instance, '_cached_label_checked') \ and instance._cached_label_checked: return + if hasattr(instance, "refresh_cache"): + instance.refresh_cache() + instance._cached_label_checked = True cached_labels = ['cached_label'] if hasattr(sender, 'CACHED_LABELS'): |