summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archaeological_context_records/models.py6
-rw-r--r--archaeological_files/models.py7
-rw-r--r--archaeological_finds/models_finds.py19
-rw-r--r--archaeological_finds/models_treatments.py6
-rw-r--r--archaeological_operations/models.py78
-rw-r--r--archaeological_warehouse/models.py41
-rw-r--r--ishtar_common/models.py41
-rw-r--r--ishtar_common/utils.py2
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)