diff options
-rw-r--r-- | archaeological_context_records/models.py | 6 | ||||
-rw-r--r-- | archaeological_files/models.py | 7 | ||||
-rw-r--r-- | archaeological_finds/models_finds.py | 19 | ||||
-rw-r--r-- | archaeological_finds/models_treatments.py | 6 | ||||
-rw-r--r-- | archaeological_operations/models.py | 78 | ||||
-rw-r--r-- | archaeological_warehouse/models.py | 41 | ||||
-rw-r--r-- | ishtar_common/models.py | 41 | ||||
-rw-r--r-- | ishtar_common/utils.py | 2 |
8 files changed, 130 insertions, 70 deletions
diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py index 3c733413b..179ed154d 100644 --- a/archaeological_context_records/models.py +++ b/archaeological_context_records/models.py @@ -925,13 +925,11 @@ class ContextRecord( ("base_finds", _("List of associated base finds")), ] - def get_values(self, prefix="", no_values=False, filtr=None, **kwargs): + def get_extra_values(self, prefix="", no_values=False, filtr=None, **kwargs): + values = {} no_base_finds = True if "no_base_finds" in kwargs: no_base_finds = kwargs["no_base_finds"] - values = super(ContextRecord, self).get_values( - prefix=prefix, no_values=no_values, filtr=filtr, **kwargs - ) if prefix and no_base_finds or kwargs.get("force_no_base_finds", True): return values diff --git a/archaeological_files/models.py b/archaeological_files/models.py index 513dbace2..624ae470d 100644 --- a/archaeological_files/models.py +++ b/archaeological_files/models.py @@ -1002,11 +1002,8 @@ class File( values[prefix + key_time_worked] = value return values - def get_values(self, prefix="", no_values=False, filtr=None, **kwargs): - values = super(File, self).get_values( - prefix=prefix, no_values=no_values, filtr=filtr, **kwargs - ) - values = get_values_town_related(self, prefix, values, filtr=filtr) + def get_extra_values(self, prefix="", no_values=False, filtr=None, **kwargs): + values = get_values_town_related(self, prefix, {}, filtr=filtr) values = self.get_dynamic_values(prefix, values, filtr=filtr) return values diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py index 7e153c6b5..6cb1499ca 100644 --- a/archaeological_finds/models_finds.py +++ b/archaeological_finds/models_finds.py @@ -670,11 +670,9 @@ class BaseFind( ) return dct - def get_values(self, prefix="", no_values=False, filtr=None, **kwargs): + def get_extra_values(self, prefix="", no_values=False, filtr=None, **kwargs): + values = {} no_find = kwargs.get("no_find", False) - values = super(BaseFind, self).get_values( - prefix=prefix, no_values=no_values, filtr=filtr, **kwargs - ) if not filtr or prefix + "complete_id" in filtr: values[prefix + "complete_id"] = self.complete_id() if no_find: @@ -917,9 +915,10 @@ class FindBasket(Basket, MainItem, ValueGetter): base_exclude.append(prefix + "items") kw = kwargs.copy() kw["exclude"] = base_exclude - values = super(FindBasket, self).get_values( - prefix=prefix, no_values=no_values, filtr=filtr, **kw - ) + return super().get_values(prefix=prefix, no_values=no_values, filtr=filtr, **kw) + + def get_extra_values(self, prefix="", no_values=False, filtr=None, **kwargs): + values = {} if not filtr or prefix + "items" in filtr: values[prefix + "items"] = [ item.get_values(no_values=True, filtr=filtr, **kwargs) @@ -2557,13 +2556,11 @@ class Find( recommendations.add(recommendation) return ", ".join(sorted(recommendations)) - def get_values(self, prefix="", no_values=False, filtr=None, **kwargs): + def get_extra_values(self, prefix="", no_values=False, filtr=None, **kwargs): + values = {} no_base_finds = False if "no_base_finds" in kwargs: no_base_finds = kwargs["no_base_finds"] - values = super(Find, self).get_values( - prefix=prefix, no_values=no_values, filtr=filtr, **kwargs - ) if not filtr or prefix + "material_types_label" in filtr: values[prefix + "material_types_label"] = self.get_material_types() if not filtr or prefix + "material_types_code" in filtr: diff --git a/archaeological_finds/models_treatments.py b/archaeological_finds/models_treatments.py index 9e62bcb29..abd5de98b 100644 --- a/archaeological_finds/models_treatments.py +++ b/archaeological_finds/models_treatments.py @@ -414,10 +414,8 @@ class Treatment( ] return actions - def get_values(self, prefix="", no_values=False, filtr=None, **kwargs): - values = super(Treatment, self).get_values( - prefix=prefix, no_values=no_values, filtr=filtr, **kwargs - ) + def get_extra_values(self, prefix="", no_values=False, filtr=None, **kwargs): + values = {} if not filtr or prefix + "upstream_finds" in filtr: values[prefix + "upstream_finds"] = " ; ".join( str(up) for up in self.upstream.all() diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py index cc5c53b45..c6bc25615 100644 --- a/archaeological_operations/models.py +++ b/archaeological_operations/models.py @@ -1603,39 +1603,55 @@ class Operation( DOC_VALUES = [ ("context_records", _("List of associated context records")), - ("containers", _("List of associated containers")), + ("containers", _("List of containers with finds related to this operation")), + ("document_containers", _("List of containers with documents related to this operation")), + ("all_containers", _("List of containers with finds or documents related to this operation")) ] - def get_containers_values(self, filtr, exclude) -> list: # Container value - # list - Container = apps.get_model("archaeological_warehouse", "Container") - containers = [] - q = Container.objects.filter( - finds__base_finds__context_record__operation=self - ).distinct("index") + def _get_containers_values(self, query, filtr, exclude) -> list: # Container value exclude += ["operation", "context_record"] - for c in q.order_by("index").all(): + containers = [] + for c in query.order_by("index").distinct().all(): containers.append(c.get_values(filtr=filtr, exclude=exclude)) return containers - def get_values(self, prefix="", no_values=False, filtr=None, **kwargs): - values = super(Operation, self).get_values( - prefix=prefix, no_values=no_values, filtr=filtr, **kwargs - ) + def get_containers_values(self, filtr, exclude) -> list: # Container value + return self._get_containers_values(self.containers_q, filtr, exclude) + + def get_document_containers_values(self, filtr, exclude) -> list: # Container value + return self._get_containers_values(self.document_containers_q, filtr, exclude) + + def get_extra_values(self, prefix="", no_values=False, filtr=None, **kwargs): + values = {} values = get_values_town_related(self, prefix, values, filtr=filtr) exclude = kwargs.get("exclude", []) + if filtr and "uuid" not in filtr: + filtr.append("uuid") + containers = [] + if (not filtr or (f"{prefix}containers" in filtr or f"{prefix}all_containers" in filtr)): + containers = self.get_containers_values(filtr, exclude) + values[f"{prefix}containers"] = containers[:] + document_containers = [] + if not filtr or (f"{prefix}document_containers" in filtr or f"{prefix}all_containers" in filtr): + document_containers = self.get_document_containers_values(filtr, exclude) + values[f"{prefix}document_containers"] = document_containers[:] + if not filtr or f"{prefix}all_containers" in filtr: + values[f"{prefix}all_containers"] = containers[:] + current_ids = [container["uuid"] for container in containers] + for container in document_containers: + if container["uuid"] not in current_ids: + values[f"{prefix}all_containers"].append(container) if prefix: return values + # context_records only when there is no prefix if ( - not filtr or "context_records" in filtr + not filtr or "context_records" in filtr ) and "context_records" not in exclude: kwargs["no_base_finds"] = False values["context_records"] = [ cr.get_values(prefix=prefix, no_values=True, filtr=None, **kwargs) for cr in self.context_record.all() ] - if (not filtr or "containers" in filtr) and "context_records" not in exclude: - values["containers"] = self.get_containers_values(filtr, exclude) return values def public_representation(self): @@ -1868,12 +1884,32 @@ class Operation( finds__base_finds__context_record__operation=self ) - def containers_q(self): - from archaeological_warehouse.models import Container - - return Container.objects.filter( + @property + def containers_q(self): # -> Container queryset + """ + Containers with finds related to this operation + """ + Container = apps.get_model("archaeological_warehouse", "Container") + q = Container.objects.filter( finds__base_finds__context_record__operation=self - ) + ).distinct("location", "index") + return q + + @property + def document_containers_q(self): # -> Container queryset + """ + Containers with documents related to this operation + """ + q = (Q(operations=self) | + Q(context_records__operation=self) | + Q(finds__base_finds__context_record__operation=self)) + q_doc = Document.objects.filter(q) + + Container = apps.get_model("archaeological_warehouse", "Container") + q = Container.objects.filter( + pk__in=list(q_doc.values_list("container_id", flat=True)) + ).distinct("location", "index") + return q def get_extra_actions(self, request): """ diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py index 5df824d8f..5e1477129 100644 --- a/archaeological_warehouse/models.py +++ b/archaeological_warehouse/models.py @@ -25,7 +25,7 @@ import uuid from django.contrib.gis.db import models from django.contrib.postgres.indexes import GinIndex from django.core.exceptions import ObjectDoesNotExist -from django.db.models import Q, Max, Count +from django.db.models import Q, Max from django.db.models.signals import post_save, post_delete, m2m_changed, pre_delete from django.template.defaultfilters import slugify from django.urls import reverse @@ -33,7 +33,7 @@ from ishtar_common.utils import ugettext_lazy as _, pgettext_lazy from django.apps import apps from ishtar_common.data_importer import post_importer_action, pre_importer_action, ImporterError -from ishtar_common.model_managers import ExternalIdManager, UUIDModelManager +from ishtar_common.model_managers import UUIDModelManager from ishtar_common.models import ValueGetter, get_current_profile, HistoryModel, Imported from ishtar_common.models_common import ( GeneralType, @@ -45,7 +45,6 @@ from ishtar_common.models_common import ( DashboardFormItem, document_attached_changed, SearchAltName, - DynamicRequest, GeoItem, CompleteIdentifierItem, SearchVectorConfig, @@ -1508,16 +1507,26 @@ class Container( def get_town_polygons(self): return self.location.get_town_polygons() + @property def contained_documents(self): - if not self.pk: - return + """ + Documents contained in this container. + A Document queryset is returned + """ Document = apps.get_model("ishtar_common", "Document") + if not self.pk: + return Document.objects.filter(pk__isnull=True) return Document.objects.filter(container_id=self.pk) + @property def contained_documents_ref(self): - if not self.pk: - return + """ + Documents whose reference container is this container. + A Document queryset is returned + """ Document = apps.get_model("ishtar_common", "Document") + if not self.pk: + return Document.objects.filter(pk__isnull=True) return Document.objects.filter(container_ref_id=self.pk) @property @@ -1811,6 +1820,8 @@ class Container( ("material_types", _("Material types inside the container - string")), ("material_types_code", _("Material types code - string")), ("finds", _("List of associated finds")), + ("contained_documents", _("List of documents contained in this container")), + ("contained_documents_ref", _("List of documents whose reference container is this container")), ] def get_material_types_code(self) -> str: @@ -1835,10 +1846,8 @@ class Container( materials.add(material) return ", ".join(sorted(materials)) - def get_values(self, prefix="", no_values=False, filtr=None, **kwargs): - values = super(Container, self).get_values( - prefix=prefix, no_values=no_values, filtr=filtr, **kwargs - ) + def get_extra_values(self, prefix="", no_values=False, filtr=None, **kwargs): + values = {} from_find = prefix.startswith("container_") or prefix.startswith( "container_ref_" ) @@ -1855,6 +1864,16 @@ class Container( f.get_values(prefix=prefix, no_values=True, filtr=filtr, **kwargs) for f in self.finds.distinct().order_by("index").all() ] + if not filtr or prefix + "contained_documents" in filtr: + values[prefix + "contained_documents"] = [ + doc.get_values(prefix=prefix, no_values=True, filtr=filtr, **kwargs) + for doc in self.contained_documents.distinct().order_by("index").all() + ] + if not filtr or prefix + "contained_documents_ref" in filtr: + values[prefix + "contained_documents_ref"] = [ + doc.get_values(prefix=prefix, no_values=True, filtr=filtr, **kwargs) + for doc in self.contained_documents_ref.distinct().order_by("index").all() + ] if not self.finds.count(): return values diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 5fb370362..bf523632a 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -307,9 +307,23 @@ class ValueGetter: return return [k[len(prefix) :] for k in filtr if k.startswith(prefix)] + def get_extra_values(self, prefix="", no_values=False, filtr=None, **kwargs): + return {} + def get_values(self, prefix="", no_values=False, filtr=None, **kwargs): if not prefix: prefix = self._prefix + extra_args = ["getvalues", str(self.pk), prefix, "1" if no_values else "0"] + if filtr: + extra_args += filtr + for k in kwargs: + extra_args += [k, str(kwargs[k])] + cache_key, values = get_cache( + self.__class__, + extra_args=extra_args + ) + if values: + return values exclude = kwargs.get("exclude", []) values = {} if ( @@ -360,8 +374,12 @@ class ValueGetter: if val.endswith(".None"): val = "" values[key] = val + values.update( + self.get_extra_values(prefix=prefix, no_values=no_values, filtr=filtr, **kwargs) + ) + # do not provide KEYS and VALUES for sub-items if (prefix and prefix != self._prefix) or no_values: - # do not provide KEYS and VALUES for sub-items + cache.set(cache_key, values, 10) return values value_list = [] for key, value_ in values.items(): @@ -370,6 +388,7 @@ class ValueGetter: value_list.append((key, str(value_))) for global_var in GlobalVar.objects.all(): values[global_var.slug] = global_var.value or "" + cache.set(cache_key, values, 10) return values @classmethod @@ -2517,8 +2536,8 @@ def documentation_get_gender_values(): class BaseGenderedType(ValueGetter): - def get_values(self, prefix="", **kwargs): - dct = super(BaseGenderedType, self).get_values(prefix=prefix, **kwargs) + def get_extra_values(self, prefix="", **kwargs): + dct = {} if not hasattr(self, "grammatical_gender"): raise NotImplementedError("This model should have a grammatical_gender field") dct[prefix + "grammatical_gender"] = self.grammatical_gender @@ -2801,8 +2820,8 @@ class TitleType(GenderedType): doc += ", **long_title** {}".format(_("Long title")) return doc - def get_values(self, prefix="", **kwargs): - dct = super(TitleType, self).get_values(prefix=prefix, **kwargs) + def get_extra_values(self, prefix="", **kwargs): + dct = super().get_extra_values(prefix=prefix, **kwargs) dct[prefix + "long_title"] = self.long_title return dct @@ -3049,10 +3068,8 @@ class Person(Address, Merge, OwnPerms, ValueGetter, MainItem): values.append(attached_to) return " ".join(values) - def get_values(self, prefix="", no_values=False, filtr=None, **kwargs): - values = super(Person, self).get_values( - prefix=prefix, no_values=no_values, filtr=filtr, **kwargs - ) + def get_extra_values(self, prefix="", no_values=False, filtr=None, **kwargs): + values = {} if not self.attached_to: values.update(Person.get_empty_values(prefix=prefix + "attached_to_")) return values @@ -4936,10 +4953,8 @@ class Document( return "" return self.image.path - def get_values(self, prefix="", no_values=False, filtr=None, **kwargs): - values = super(Document, self).get_values( - prefix=prefix, no_values=no_values, filtr=filtr, **kwargs - ) + def get_extra_values(self, prefix="", no_values=False, filtr=None, **kwargs): + values = {} if not filtr or prefix + "image_path" in filtr: values[prefix + "image_path"] = self.image_path if not filtr or prefix + "thumbnail_path" in filtr: diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py index 92059c195..d55687cd7 100644 --- a/ishtar_common/utils.py +++ b/ishtar_common/utils.py @@ -687,7 +687,7 @@ def get_cache(cls, extra_args=tuple(), app_label=None): if len(cache_key) >= 250: # nosec: used for a cache key no consequence if predictable m = hashlib.md5() # nosec - m.update(cache_key) + m.update(cache_key.encode("utf-8")) cache_key = m.hexdigest() return cache_key, cache.get(cache_key) |