diff options
-rw-r--r-- | archaeological_context_records/forms.py | 5 | ||||
-rw-r--r-- | archaeological_context_records/models.py | 3 | ||||
-rw-r--r-- | archaeological_files/forms.py | 18 | ||||
-rw-r--r-- | archaeological_files/models.py | 4 | ||||
-rw-r--r-- | archaeological_warehouse/forms.py | 20 | ||||
-rw-r--r-- | archaeological_warehouse/models.py | 12 | ||||
-rw-r--r-- | ishtar_common/forms_common.py | 9 | ||||
-rw-r--r-- | ishtar_common/models.py | 7 | ||||
-rw-r--r-- | ishtar_common/models_common.py | 10 | ||||
-rw-r--r-- | ishtar_common/views_item.py | 159 |
10 files changed, 171 insertions, 76 deletions
diff --git a/archaeological_context_records/forms.py b/archaeological_context_records/forms.py index eb6b57b63..95980b34e 100644 --- a/archaeological_context_records/forms.py +++ b/archaeological_context_records/forms.py @@ -32,10 +32,11 @@ from django.forms.formsets import formset_factory from ishtar_common.utils import get_current_profile, ugettext_lazy as _ from ishtar_common.models import ( - valid_id, + Area, IshtarSiteProfile, Town, SpatialReferenceSystem, + valid_id, valid_ids, ) from archaeological_context_records import models @@ -140,6 +141,7 @@ class RecordSelect(GeoItemSelect, PeriodSelect): ) label = forms.CharField(label=_("ID"), max_length=100) town = get_town_field() + area = forms.ChoiceField(label=_("Area"), choices=[]) if settings.COUNTRY == "fr": operation__code_patriarche = forms.CharField( max_length=500, widget=OAWidget, label=_("Code PATRIARCHE") @@ -189,6 +191,7 @@ class RecordSelect(GeoItemSelect, PeriodSelect): details_on_color = forms.CharField(label=_("Details on color")) TYPES = PeriodSelect.TYPES + [ + FieldType('area', Area), FieldType('cultural_attributions', models.CulturalAttributionType), FieldType("unit", models.Unit), FieldType("cr_relation_types", models.RelationType), diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py index 8046cef7e..eae4e3720 100644 --- a/archaeological_context_records/models.py +++ b/archaeological_context_records/models.py @@ -633,6 +633,9 @@ class ContextRecord( "town": SearchAltName( pgettext_lazy("key for text search", "town"), "town__cached_label__iexact" ), + "area": SearchAltName( + pgettext_lazy("key for text search", "area"), "town__areas__label__iexact" + ), "operation__year": SearchAltName( pgettext_lazy("key for text search", "operation-year"), "operation__year" ), diff --git a/archaeological_files/forms.py b/archaeological_files/forms.py index 6c18d675c..46b755ab6 100644 --- a/archaeological_files/forms.py +++ b/archaeological_files/forms.py @@ -29,26 +29,18 @@ from django.conf import settings from django.core import validators from django.db.models import Q from django.forms.formsets import formset_factory -from django.utils.functional import lazy from django.utils.safestring import mark_safe from ishtar_common.utils import ugettext_lazy as _ from ishtar_common.models import ( - Person, + Area, Organization, + organization_type_pks_lazy, + Person, + person_type_pk_lazy, Town, valid_id, valid_ids, - person_type_pks_lazy, - person_type_pk_lazy, - organization_type_pks_lazy, - organization_type_pk_lazy, - get_sra_agent_label, - get_sra_agent_head_scientist_label, - get_orga_general_contractor_label, - get_general_contractor_label, - get_orga_planning_service_label, - get_responsible_planning_service_label, ) from ishtar_common.models_common import Department from archaeological_operations.models import ActType, AdministrativeAct, OperationType @@ -93,6 +85,7 @@ class FileSelect(DocumentItemSelect): numeric_reference = forms.IntegerField(label=_("Numeric reference")) internal_reference = forms.CharField(max_length=200, label=_("Other reference")) towns = get_town_field() + area = forms.ChoiceField(label=_("Area"), choices=[]) parcel = forms.CharField(label=_("Parcel")) if settings.ISHTAR_DPTS: towns__numero_insee__startswith = forms.ChoiceField( @@ -162,6 +155,7 @@ class FileSelect(DocumentItemSelect): FieldType("monitoring_justification", models.MonitoringJustificationType), FieldType("permit_type", models.PermitType), FieldType("file_type", models.FileType), + FieldType('area', Area), ] def __init__(self, *args, **kwargs): diff --git a/archaeological_files/models.py b/archaeological_files/models.py index 2bc402f73..da36e40b7 100644 --- a/archaeological_files/models.py +++ b/archaeological_files/models.py @@ -609,6 +609,10 @@ class File( "general_contractor__attached_to__cached_label__iexact", related_name="general_contractor__attached_to" ), + "area": SearchAltName( + pgettext_lazy("key for text search", "area"), + "towns__areas__label__iexact" + ), } ALT_NAMES.update(BaseHistorizedItem.ALT_NAMES) ALT_NAMES.update(DocumentItem.ALT_NAMES) diff --git a/archaeological_warehouse/forms.py b/archaeological_warehouse/forms.py index edc4a3b74..1e1979cac 100644 --- a/archaeological_warehouse/forms.py +++ b/archaeological_warehouse/forms.py @@ -30,11 +30,12 @@ from django.forms.formsets import formset_factory from ishtar_common.utils import ugettext_lazy as _ from ishtar_common.models import ( + Area, + Organization, Person, - valid_id, - Town, SpatialReferenceSystem, - Organization, + Town, + valid_id, valid_ids, ) from archaeological_operations.models import ArchaeologicalSite @@ -148,11 +149,11 @@ class WarehouseSelect(CustomForm, TableSelect): name = forms.CharField(label=_("Name")) warehouse_type = forms.ChoiceField(label=_("Warehouse type"), choices=[]) town = get_town_field(label=_("Town")) - - def __init__(self, *args, **kwargs): - super(WarehouseSelect, self).__init__(*args, **kwargs) - self.fields["warehouse_type"].choices = models.WarehouseType.get_types() - self.fields["warehouse_type"].help_text = models.WarehouseType.get_help() + area = forms.ChoiceField(label=_("Area"), choices=[]) + TYPES = [ + FieldType('area', Area), + FieldType("warehouse_type", models.WarehouseType), + ] class WarehouseFormSelection(LockForm, CustomFormSearch): @@ -514,6 +515,8 @@ class ContainerSelect(DocumentItemSelect): ) location_name = get_warehouse_field(label=_("Warehouse")) responsibility_name = get_warehouse_field(label=_("Warehouse (responsibility)")) + town = get_town_field(label=_("Warehouse - Town")) + area = forms.ChoiceField(label=_("Warehouse - Area"), choices=[]) container_type = forms.ChoiceField(label=_("Container type"), choices=[]) reference = forms.CharField(label=_("Ref.")) code = forms.CharField(label=_("Code")) @@ -600,6 +603,7 @@ class ContainerSelect(DocumentItemSelect): treatment_emergency = forms.ChoiceField(choices=[], label=_("Treatment emergency")) TYPES = [ + FieldType('area', Area), FieldType("integrities", IntegrityType), FieldType("remarkabilities", RemarkabilityType), FieldType("conservatory_state", ConservatoryState), diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py index e985d6667..be3bdd89c 100644 --- a/archaeological_warehouse/models.py +++ b/archaeological_warehouse/models.py @@ -369,6 +369,10 @@ class Warehouse( pgettext_lazy("key for text search", "town"), "precise_town_id", ), + "area": SearchAltName( + pgettext_lazy("key for text search", "area"), + "precise_town__areas__label__iexact" + ), } GEO_LABEL = "name" CACHED_LABELS = ["cached_town_label"] @@ -1087,6 +1091,14 @@ class Container( pgettext_lazy("key for text search", "is-stationary"), "container_type__stationary", ), + "town": SearchAltName( + pgettext_lazy("key for text search", "town"), + "location__precise_town_id", + ), + "area": SearchAltName( + pgettext_lazy("key for text search", "area"), + "location__precise_town__areas__label__iexact" + ), } REVERSED_BOOL_FIELDS = [ "children__isnull", diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index 187941bb6..1858c7246 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -836,10 +836,14 @@ class OrganizationSelect(CustomForm, TableSelect): name = forms.CharField(label=_("Name"), max_length=300) organization_type = forms.ChoiceField(label=_("Type"), choices=[]) precise_town_id = get_town_field() + area = forms.ChoiceField(label=_("Area"), choices=[]) museum_museofile_id = forms.CharField(label=_("Museofile ID"), required=False) + TYPES = [ + FieldType('area', models.Area), + ] def __init__(self, *args, **kwargs): - super(OrganizationSelect, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields["organization_type"].choices = models.OrganizationType.get_types() @@ -1038,9 +1042,12 @@ class PersonSelect(CustomForm, TableSelect): ), validators=[models.valid_id(models.Organization)], ) + precise_town_id = get_town_field(required=False) + area = forms.ChoiceField(label=_("Area"), choices=[]) TYPES = [ FieldType("person_types", models.PersonType), FieldType("title", models.TitleType), + FieldType('area', models.Area), ] diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 949120383..102e01f0a 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -2641,7 +2641,8 @@ organization_type_pks_lazy = lazy(OrganizationType.get_or_create_pks, str) class Organization(Address, Merge, OwnPerms, BaseGenderedType, ValueGetter, MainItem): - TABLE_COLS = ("name", "organization_type", "address", "town") #, "precise_town") + TABLE_COLS = ("name", "organization_type", "address", "town") + # , "precise_town") SLUG = "organization" SHOW_URL = "show-organization" DELETE_URL = "delete-organization" @@ -2677,6 +2678,7 @@ class Organization(Address, Merge, OwnPerms, BaseGenderedType, ValueGetter, Main "museum_museofile_id__iexact", ), } + ALT_NAMES.update(Address.ALT_NAMES) QA_EDIT = QuickAction( url="organization-qa-bulk-update", icon_class="fa fa-pencil", @@ -2934,7 +2936,7 @@ class Person(Address, Merge, OwnPerms, ValueGetter, MainItem): "title": SearchAltName( pgettext_lazy("key for text search", "title"), "title__label__iexact", related_name="title" - ), + ), "salutation": SearchAltName( pgettext_lazy("key for text search", "salutation"), "salutation__iexact" ), @@ -2957,6 +2959,7 @@ class Person(Address, Merge, OwnPerms, ValueGetter, MainItem): "profiles__profile_type__label__iexact", ), } + ALT_NAMES.update(Address.ALT_NAMES) QA_EDIT = QuickAction( url="person-qa-bulk-update", icon_class="fa fa-pencil", diff --git a/ishtar_common/models_common.py b/ishtar_common/models_common.py index 49c69e9e1..8fb49c5cc 100644 --- a/ishtar_common/models_common.py +++ b/ishtar_common/models_common.py @@ -3880,6 +3880,16 @@ class Address(BaseHistorizedItem): ) history = HistoricalRecords(inherit=True) SUB_ADDRESSES = [] + ALT_NAMES = { + "precise_town_id": SearchAltName( + pgettext_lazy("key for text search", "town"), + "precise_town_id" + ), + "area": SearchAltName( + pgettext_lazy("key for text search", "area"), + "precise_town__areas__label__iexact" + ), + } class Meta: abstract = True diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py index cecc0318d..5d2c92899 100644 --- a/ishtar_common/views_item.py +++ b/ishtar_common/views_item.py @@ -1306,6 +1306,104 @@ def _manage_facet_search(model, dct, and_reqs): dct[k] = getattr(model, POST_PROCESS_REQUEST[k])(dct[k].replace('"', "")) +def _manage_hierarchic_precise_town(req, dct, and_reqs): + val = _clean_type_val(dct.pop(req)).strip('"') + if val.startswith('"') and val.endswith('"'): + val = val[1:-1] + vals = [v.replace('"', "") for v in val.split(";")] + town_ids = [] + Town = apps.get_model("ishtar_common", "Town") + for val in vals: + q = Town.objects.filter(cached_label__iexact=val).values_list( + "id", flat=True) + if not q.count(): + continue + town_id = q.all()[0] + town_ids.append(town_id) + for rel_query in ("parents__", "children__"): + for idx in range(HIERARCHIC_LEVELS): + k = rel_query * (idx + 1) + "pk" + q = Town.objects.filter( + **{k: town_id}).values_list("id", flat=True) + if not q.count(): + break + town_ids += list(q.all()) + main_req = Q(**{req + "__in": town_ids}) + and_reqs.append(main_req) + + +def _manage_hierarchic_precise_town_area(req, dct, and_reqs): + if req.endswith("pk"): + suffix = "pk" + elif req.endswith("label__iexact"): + suffix = "label__iexact" + else: + return + val = _clean_type_val(dct.pop(req)) + if val.startswith('"') and val.endswith('"'): + val = val[1:-1] + if val == "*": + req = req.replace("label__", "").replace("pk", "").replace( + "iexact", "" + ).replace("precise_town__areas", "precise_town_id") # * -> is attached to a town + req += "isnull" + reqs = Q(**{req: False}) + and_reqs.append(reqs) + return + elif "*" in val and "iexact" in suffix: + suffix = suffix.replace("iexact", "icontains") + req = req.replace("iexact", "icontains") + val = val.replace("*", "") + Town = apps.get_model("ishtar_common", "Town") + Area = apps.get_model("ishtar_common", "Area") + q_area = Area.objects.filter(**{suffix: val}) + q_towns = Town.objects.filter(areas__pk__in=q_area.values_list("pk", flat=True)) + req = req.replace("precise_town__areas__label__iexact", "precise_town_id__in") + val_towns = q_towns.values_list("pk", flat=True) + reqs = Q(**{req: val_towns}) + + for idx in range(HIERARCHIC_LEVELS): + suffix = "parent__" + suffix + q_area = Area.objects.filter(**{suffix: val}) + q_towns = Town.objects.filter(areas__pk__in=q_area.values_list("pk", flat=True)) + if q_towns.count(): + val_towns = q_towns.values_list("pk", flat=True) + q = Q(**{req: val_towns}) + reqs |= q + and_reqs.append(reqs) + + +def _manage_hierarchic_area(req, dct, and_reqs): + if req.endswith("pk"): + suffix = "pk" + elif req.endswith("label__iexact"): + suffix = "label__iexact" + else: + return + val = _clean_type_val(dct.pop(req)) + if val.startswith('"') and val.endswith('"'): + val = val[1:-1] + if val == "*": + req = req.replace("label__", "").replace("pk", "").replace("iexact", "") + req += "isnull" + reqs = Q(**{req: False}) + and_reqs.append(reqs) + return + elif "*" in val and "iexact" in suffix: + suffix = suffix.replace("iexact", "icontains") + req = req.replace("iexact", "icontains") + val = val.replace("*", "") + + reqs = Q(**{req: val}) + + for idx in range(HIERARCHIC_LEVELS): + req = req[: -(len(suffix))] + "parent__" + suffix + q = Q(**{req: val}) + reqs |= q + and_reqs.append(reqs) + # TODO: improve query with "IN ()"? + + def _manage_hierarchic_fields(model, dct, and_reqs): hierarchic_fields = HIERARCHIC_FIELDS[:] if hasattr(model, "hierarchic_fields"): @@ -1315,35 +1413,13 @@ def _manage_hierarchic_fields(model, dct, and_reqs): if type(reqs) not in (list, tuple): reqs = [reqs] for req in reqs: + if req.endswith( + "precise_town__areas__label__iexact" + ) or req.endswith("precise_town__areas__pk"): + _manage_hierarchic_precise_town_area(req, dct, and_reqs) + continue if req.endswith("areas__pk") or req.endswith("areas__label__iexact"): - if req.endswith("pk"): - suffix = "pk" - elif req.endswith("label__iexact"): - suffix = "label__iexact" - else: - continue - val = _clean_type_val(dct.pop(req)) - if val.startswith('"') and val.endswith('"'): - val = val[1:-1] - if val == "*": - req = req.replace("label__", "").replace("pk", "").replace("iexact", "") - req += "isnull" - reqs = Q(**{req: False}) - and_reqs.append(reqs) - continue - elif "*" in val and "iexact" in suffix: - suffix = suffix.replace("iexact", "icontains") - req = req.replace("iexact", "icontains") - val = val.replace("*", "") - - reqs = Q(**{req: val}) - - for idx in range(HIERARCHIC_LEVELS): - req = req[: -(len(suffix))] + "parent__" + suffix - q = Q(**{req: val}) - reqs |= q - and_reqs.append(reqs) - # TODO: improve query with "IN ()"? + _manage_hierarchic_area(req, dct, and_reqs) continue if req.endswith("wcontainer_id") or req.endswith("wcontainer_ref_id"): @@ -1371,32 +1447,11 @@ def _manage_hierarchic_fields(model, dct, and_reqs): container_ids += list(q.all()) main_req = Q(**{req + "__in": container_ids}) and_reqs.append(main_req) + continue if req.endswith("precise_town_id"): - val = _clean_type_val(dct.pop(req)).strip('"') - if val.startswith('"') and val.endswith('"'): - val = val[1:-1] - vals = [v.replace('"', "") for v in val.split(";")] - town_ids = [] - for val in vals: - q = Town.objects.filter(cached_label__iexact=val).values_list( - "id", flat=True) - if not q.count(): - continue - town_id = q.all()[0] - town_ids.append(town_id) - reqs = Q(**{req: val}) - for rel_query in ("parents__", "children__"): - for idx in range(HIERARCHIC_LEVELS): - k = rel_query * (idx + 1) + "pk" - q = Town.objects.filter( - **{k: town_id}).values_list("id", flat=True) - if not q.count(): - break - town_ids += list(q.all()) - main_req = Q(**{req + "__in": town_ids}) - and_reqs.append(main_req) - + _manage_hierarchic_precise_town(req, dct, and_reqs) + continue elif ( req.endswith("town__pk") or req.endswith("towns__pk") |