diff options
| author | Étienne Loks <etienne.loks@iggdrasil.net> | 2026-06-28 17:01:05 +0200 |
|---|---|---|
| committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2026-06-28 22:09:50 +0200 |
| commit | 46df68944a355b2509596c94b80594d1b0c9736f (patch) | |
| tree | 863ed5a1f6e479aba8e315d675a44dd04e27137d | |
| parent | e15f03188cb0be5925f768f26ef077bf78c1783b (diff) | |
| download | Ishtar-46df68944a355b2509596c94b80594d1b0c9736f.tar.bz2 Ishtar-46df68944a355b2509596c94b80594d1b0c9736f.zip | |
✨ sites - db new field: "other name" ; finds - db new fields: "recommendations" and "current storage conditions"
8 files changed, 915 insertions, 2 deletions
diff --git a/archaeological_finds/admin.py b/archaeological_finds/admin.py index ffff0adc2..b7d0052bd 100644 --- a/archaeological_finds/admin.py +++ b/archaeological_finds/admin.py @@ -273,6 +273,16 @@ class RecommendedTreatmentTypeAdmin(GeneralTypeAdmin): LIST_DISPLAY = ["label", "txt_idx", "available", "parent", "order", "comment"] +@admin.register(models.CurrentStorageConditionType, site=admin_site) +class CurrentStorageConditionTypeAdmin(GeneralTypeAdmin): + LIST_DISPLAY = ["label", "txt_idx", "available", "parent", "order", "comment"] + + +@admin.register(models.RecommendationType, site=admin_site) +class RecommendationTypeAdmin(GeneralTypeAdmin): + LIST_DISPLAY = ["label", "txt_idx", "available", "parent", "order", "comment"] + + general_models = [ models.AlterationCauseType, models.AlterationType, models.BatchType, models.CollectionEntryModeType, models.IconographicPatternType, models.IntegrityType, diff --git a/archaeological_finds/migrations/0159_find_current_storage_conditions_preconisations.py b/archaeological_finds/migrations/0159_find_current_storage_conditions_preconisations.py new file mode 100644 index 000000000..44488d802 --- /dev/null +++ b/archaeological_finds/migrations/0159_find_current_storage_conditions_preconisations.py @@ -0,0 +1,83 @@ +# Generated by Django 4.2.21 on 2026-06-28 17:40 + +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion +import ishtar_common.models_common +import re + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0158_statementcondition_add_fields'), + ] + + operations = [ + migrations.AddField( + model_name='find', + name='cached_current_storage_conditions', + field=models.TextField(blank=True, default='', help_text='Generated automatically - do not edit', verbose_name='Cached current storage conditions'), + ), + migrations.AddField( + model_name='find', + name='cached_recommendations', + field=models.TextField(blank=True, default='', help_text='Generated automatically - do not edit', verbose_name='Cached recommendations label'), + ), + migrations.AddField( + model_name='historicalfind', + name='cached_current_storage_conditions', + field=models.TextField(blank=True, default='', help_text='Generated automatically - do not edit', verbose_name='Cached current storage conditions'), + ), + migrations.AddField( + model_name='historicalfind', + name='cached_recommendations', + field=models.TextField(blank=True, default='', help_text='Generated automatically - do not edit', verbose_name='Cached recommendations label'), + ), + migrations.CreateModel( + name='RecommendationType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('label', models.TextField(verbose_name='Label')), + ('txt_idx', models.TextField(help_text='The slug is the standardized version of the name. It contains only lowercase letters, numbers and hyphens. Each slug must be unique.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), 'Enter a valid “slug” consisting of letters, numbers, underscores or hyphens.', 'invalid')], verbose_name='Textual ID')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('available', models.BooleanField(default=True, verbose_name='Available')), + ('order', models.IntegerField(default=10, verbose_name='Order')), + ('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='archaeological_finds.recommendationtype', verbose_name='Parent')), + ], + options={ + 'verbose_name': 'Recommendation type', + 'verbose_name_plural': 'Recommendation types', + 'ordering': ('parent__order', 'parent__label', 'order', 'label'), + }, + bases=(ishtar_common.models_common.Cached, models.Model), + ), + migrations.CreateModel( + name='CurrentStorageConditionType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('label', models.TextField(verbose_name='Label')), + ('txt_idx', models.TextField(help_text='The slug is the standardized version of the name. It contains only lowercase letters, numbers and hyphens. Each slug must be unique.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), 'Enter a valid “slug” consisting of letters, numbers, underscores or hyphens.', 'invalid')], verbose_name='Textual ID')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('available', models.BooleanField(default=True, verbose_name='Available')), + ('order', models.IntegerField(default=10, verbose_name='Order')), + ('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='archaeological_finds.currentstorageconditiontype', verbose_name='Parent')), + ], + options={ + 'verbose_name': 'Current storage condition type', + 'verbose_name_plural': 'Current storage condition types', + 'ordering': ('parent__order', 'parent__label', 'order', 'label'), + }, + bases=(ishtar_common.models_common.Cached, models.Model), + ), + migrations.AddField( + model_name='find', + name='current_storage_conditions', + field=models.ManyToManyField(blank=True, related_name='finds', to='archaeological_finds.currentstorageconditiontype', verbose_name='Current storage conditions'), + ), + migrations.AddField( + model_name='find', + name='recommendations', + field=models.ManyToManyField(blank=True, related_name='finds', to='archaeological_finds.recommendationtype', verbose_name='Recommendations'), + ), + ] diff --git a/archaeological_finds/migrations/0160_data_migration.json b/archaeological_finds/migrations/0160_data_migration.json new file mode 100644 index 000000000..cc7aa383f --- /dev/null +++ b/archaeological_finds/migrations/0160_data_migration.json @@ -0,0 +1,691 @@ +[ + { + "model": "archaeological_finds.currentstorageconditiontype", + "fields": { + "label": "En vitrine", + "txt_idx": "en-vitrine", + "comment": "", + "available": true, + "order": 100, + "parent": null + } + }, + { + "model": "archaeological_finds.currentstorageconditiontype", + "fields": { + "label": "En r\u00e9serve", + "txt_idx": "en-reserve", + "comment": "", + "available": true, + "order": 200, + "parent": null + } + }, + { + "model": "archaeological_finds.currentstorageconditiontype", + "fields": { + "label": "En ext\u00e9rieur", + "txt_idx": "en-exterieur", + "comment": "", + "available": true, + "order": 300, + "parent": null + } + }, + { + "model": "archaeological_finds.currentstorageconditiontype", + "fields": { + "label": "Hygrom\u00e9trie", + "txt_idx": "hygrometrie", + "comment": "", + "available": true, + "order": 400, + "parent": null + } + }, + { + "model": "archaeological_finds.currentstorageconditiontype", + "fields": { + "label": "Soclage", + "txt_idx": "soclage", + "comment": "", + "available": true, + "order": 500, + "parent": null + } + }, + { + "model": "archaeological_finds.currentstorageconditiontype", + "fields": { + "label": "En vitrine climatique", + "txt_idx": "en-vitrine-climatique", + "comment": "", + "available": true, + "order": 110, + "parent": [ + "en-vitrine" + ] + } + }, + { + "model": "archaeological_finds.currentstorageconditiontype", + "fields": { + "label": "En vitrine herm\u00e9tique", + "txt_idx": "en-vitrine-hermetique", + "comment": "", + "available": true, + "order": 120, + "parent": [ + "en-vitrine" + ] + } + }, + { + "model": "archaeological_finds.currentstorageconditiontype", + "fields": { + "label": "En vitrine non herm\u00e9tique", + "txt_idx": "en-vitrine-non-hermetique", + "comment": "", + "available": true, + "order": 130, + "parent": [ + "en-vitrine" + ] + } + }, + { + "model": "archaeological_finds.currentstorageconditiontype", + "fields": { + "label": "Contenant herm\u00e9tique", + "txt_idx": "contenant-hermetique", + "comment": "", + "available": true, + "order": 210, + "parent": [ + "en-reserve" + ] + } + }, + { + "model": "archaeological_finds.currentstorageconditiontype", + "fields": { + "label": "Contenant non herm\u00e9tique", + "txt_idx": "contenant-non-hermetique", + "comment": "", + "available": true, + "order": 220, + "parent": [ + "en-reserve" + ] + } + }, + { + "model": "archaeological_finds.currentstorageconditiontype", + "fields": { + "label": "Avec agent dess\u00e9chant", + "txt_idx": "avec-agent-dessechant", + "comment": "", + "available": true, + "order": 230, + "parent": [ + "en-reserve" + ] + } + }, + { + "model": "archaeological_finds.currentstorageconditiontype", + "fields": { + "label": "Contr\u00f4le de l'hygrom\u00e9trie", + "txt_idx": "controle-de-lhygrometrie", + "comment": "", + "available": true, + "order": 410, + "parent": [ + "hygrometrie" + ] + } + }, + { + "model": "archaeological_finds.currentstorageconditiontype", + "fields": { + "label": "Pas de contr\u00f4le de l'hygrom\u00e9trie", + "txt_idx": "pas-de-controle-de-lhygrometrie", + "comment": "", + "available": true, + "order": 420, + "parent": [ + "hygrometrie" + ] + } + }, + { + "model": "archaeological_finds.currentstorageconditiontype", + "fields": { + "label": "Soclage adapt\u00e9", + "txt_idx": "soclage-adapte", + "comment": "", + "available": true, + "order": 510, + "parent": [ + "soclage" + ] + } + }, + { + "model": "archaeological_finds.currentstorageconditiontype", + "fields": { + "label": "Soclage inadapt\u00e9", + "txt_idx": "soclage-inadapte", + "comment": "", + "available": true, + "order": 520, + "parent": [ + "soclage" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Conditionnement", + "txt_idx": "conditionnement", + "comment": "", + "available": true, + "order": 100, + "parent": null + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Manipulations", + "txt_idx": "manipulations", + "comment": "", + "available": true, + "order": 200, + "parent": null + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Pr\u00e9sentation", + "txt_idx": "presentation", + "comment": "", + "available": true, + "order": 300, + "parent": null + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Soclage", + "txt_idx": "soclage", + "comment": "", + "available": true, + "order": 400, + "parent": null + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Environnement", + "txt_idx": "environnement", + "comment": "", + "available": true, + "order": 500, + "parent": null + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Lumi\u00e8re", + "txt_idx": "lumiere", + "comment": "", + "available": true, + "order": 600, + "parent": null + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Hygrom\u00e9trie", + "txt_idx": "hygrometrie", + "comment": "", + "available": true, + "order": 700, + "parent": null + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Temp\u00e9rature", + "txt_idx": "temperature", + "comment": "", + "available": true, + "order": 800, + "parent": null + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Caler \u00e0 l'aide de mousses de type Plastazote (PE)", + "txt_idx": "caler-a-laide-de-mousses", + "comment": "", + "available": true, + "order": 110, + "parent": [ + "conditionnement" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Emballer dans du papier de soie", + "txt_idx": "emballer-dans-du-papier-de-soie", + "comment": "", + "available": true, + "order": 120, + "parent": [ + "conditionnement" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Transporter dans une caisse \u00e9crin", + "txt_idx": "transporter-dans-une-caisse-ecrin", + "comment": "", + "available": true, + "order": 130, + "parent": [ + "conditionnement" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Transporter dans une caisse \u00e9crin avec pieds anti-vibration", + "txt_idx": "transporter-dans-une-caisse-ecrin-avec-pieds-anti-vibration", + "comment": "", + "available": true, + "order": 140, + "parent": [ + "conditionnement" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Transporter dans une caisse rigide de type norme Europe", + "txt_idx": "transporter-dans-une-caisse-rigide-de-type-norme-europe", + "comment": "", + "available": true, + "order": 150, + "parent": [ + "conditionnement" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Manipuler avec des gants en nitrile ou des mains propres", + "txt_idx": "manipuler-avec-des-gants", + "comment": "", + "available": true, + "order": 210, + "parent": [ + "manipulations" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Manipuler avec un support pour \u00e9viter de faire c\u00e9der le collage", + "txt_idx": "manipuler-avec-un-support", + "comment": "", + "available": true, + "order": 220, + "parent": [ + "manipulations" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Risque de rupture ou d\u2019alt\u00e9ration de l\u2019objet", + "txt_idx": "risque-de-rupture-ou-dalteration-de-lobjet", + "comment": "", + "available": true, + "order": 230, + "parent": [ + "manipulations" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Limiter l'exposition aux vibrations", + "txt_idx": "limiter-exposition-aux-vibrations", + "comment": "", + "available": true, + "order": 310, + "parent": [ + "presentation" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Ne pas poser sur un support abrasif", + "txt_idx": "pas-de-support-abrasif", + "comment": "", + "available": true, + "order": 320, + "parent": [ + "presentation" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Placer un intercalaire entre le fond de vitrine et l'objet (M\u00e9linex, plastazote...)", + "txt_idx": "intercalaire", + "comment": "", + "available": true, + "order": 330, + "parent": [ + "presentation" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Pr\u00e9sence d'un tiroir pour agent dessicant", + "txt_idx": "agent-dessicant", + "comment": "", + "available": true, + "order": 340, + "parent": [ + "presentation" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Vitrine herm\u00e9tique avec contr\u00f4le de l'hygrom\u00e9trie", + "txt_idx": "vitrine-hermetique-hygrometrie", + "comment": "", + "available": true, + "order": 350, + "parent": [ + "presentation" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Attention, collages fragiles", + "txt_idx": "attention-collages-fragiles", + "comment": "", + "available": true, + "order": 410, + "parent": [ + "soclage" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "La r\u00e9alisation du soclage doit \u00eatre soumise \u00e0 l'approbation pr\u00e9alable des propri\u00e9taires de l'objet", + "txt_idx": "approbation-soclage", + "comment": "", + "available": true, + "order": 420, + "parent": [ + "soclage" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Pr\u00e9senter \u00e0 plat ou pr\u00e9voir un soclage adapt\u00e9 \u00e0 l'objet de mani\u00e8re \u00e0 assurer son maintien", + "txt_idx": "presentation-a-plat", + "comment": "", + "available": true, + "order": 430, + "parent": [ + "soclage" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Pr\u00e9voir un soclage adapt\u00e9 \u00e0 l'objet", + "txt_idx": "soclage-adapte", + "comment": "", + "available": true, + "order": 440, + "parent": [ + "soclage" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "S'il est ind\u00e9pendant des structures mus\u00e9ographiques, le soclage sera restitu\u00e9 avec l'objet", + "txt_idx": "restituer-soclage", + "comment": "", + "available": true, + "order": 450, + "parent": [ + "soclage" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Utiliser le soclage transmis avec l\u2019objet", + "txt_idx": "utiliser-soclage-transmis", + "comment": "", + "available": true, + "order": 460, + "parent": [ + "soclage" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Hygrom\u00e9trie et temp\u00e9rature stables", + "txt_idx": "hygrometrie-et-temperature-stables", + "comment": "", + "available": true, + "order": 510, + "parent": [ + "environnement" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Pas de lumi\u00e8re directe sur l'objet", + "txt_idx": "pas-de-lumiere-directe", + "comment": "", + "available": true, + "order": 520, + "parent": [ + "environnement" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Pas de lumi\u00e8re qui chauffe dans la vitrine", + "txt_idx": "pas-de-lumiere-qui-chauffe", + "comment": "", + "available": true, + "order": 530, + "parent": [ + "environnement" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Pr\u00e9sence dans la vitrine d\u2019un stabilisateur d\u2019humidit\u00e9 \u00e0 l'hygrom\u00e9trie conseill\u00e9e", + "txt_idx": "presence-stabilisateur-humidite", + "comment": "", + "available": true, + "order": 540, + "parent": [ + "environnement" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Pr\u00e9sence dans la vitrine d\u2019un absorbeur de polluants", + "txt_idx": "presence-absorbeur-polluants", + "comment": "", + "available": true, + "order": 550, + "parent": [ + "environnement" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "< 150 Lux", + "txt_idx": "inferieur-150-lux", + "comment": "", + "available": true, + "order": 610, + "parent": [ + "lumiere" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "150 Lux", + "txt_idx": "150-lux", + "comment": "", + "available": true, + "order": 620, + "parent": [ + "lumiere" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "< 30%", + "txt_idx": "inferieur-30pc", + "comment": "", + "available": true, + "order": 710, + "parent": [ + "hygrometrie" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "40-45% +/- 10%", + "txt_idx": "40-45pc", + "comment": "", + "available": true, + "order": 720, + "parent": [ + "hygrometrie" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "50% +/- 10%", + "txt_idx": "50pc", + "comment": "", + "available": true, + "order": 730, + "parent": [ + "hygrometrie" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "21 +/- 2\u00b0C", + "txt_idx": "21-2c", + "comment": "", + "available": true, + "order": 810, + "parent": [ + "temperature" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Risque de rupture des collages", + "txt_idx": "risque-de-rupture-des-collages", + "comment": "", + "available": true, + "order": 240, + "parent": [ + "risque-de-rupture-ou-dalteration-de-lobjet" + ] + } + }, + { + "model": "archaeological_finds.recommendationtype", + "fields": { + "label": "Risque d'effritement des surfaces", + "txt_idx": "risque-deffritement-des-surfaces", + "comment": "", + "available": true, + "order": 250, + "parent": [ + "risque-de-rupture-ou-dalteration-de-lobjet" + ] + } + } +] diff --git a/archaeological_finds/migrations/0160_data_migration_recommandations_storage_conditions.py b/archaeological_finds/migrations/0160_data_migration_recommandations_storage_conditions.py new file mode 100644 index 000000000..dab7320b6 --- /dev/null +++ b/archaeological_finds/migrations/0160_data_migration_recommandations_storage_conditions.py @@ -0,0 +1,26 @@ +# Generated by Django 2.2.24 on 2024-02-10 12:07 + +import os + +from django.db import migrations +from django.core.management import call_command + + +def load_data(apps, __): + RecommendationType = apps.get_model("archaeological_finds", + "RecommendationType") + if not RecommendationType.objects.count(): + json_path = os.sep.join(os.path.abspath(__file__).split(os.sep)[:-1] + [ + "0160_data_migration.json"]) + call_command("loaddata", json_path) + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0159_find_current_storage_conditions_preconisations'), + ] + + operations = [ + migrations.RunPython(load_data) + ] diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py index 12e6a05cb..3c48b9dee 100644 --- a/archaeological_finds/models.py +++ b/archaeological_finds/models.py @@ -8,6 +8,7 @@ from archaeological_finds.models_finds import ( CollectionEntryModeType, CommunicabilityType, ConservatoryState, + CurrentStorageConditionType, DiscoveryMethod, FBulkView, Find, @@ -34,6 +35,7 @@ from archaeological_finds.models_finds import ( OwnershipStatus, OwnerType, Property, + RecommendationType, RecommendedTreatmentType, RemarkabilityType, TechnicalAreaType, @@ -72,6 +74,7 @@ __all__ = [ "CollectionEntryModeType", "CommunicabilityType", "ConservatoryState", + "CurrentStorageConditionType", "DiscoveryMethod", "Exhibition", "ExhibitionType", @@ -105,6 +108,7 @@ __all__ = [ "OwnershipStatus", "OwnerType", "Property", + "RecommendationType", "RemarkabilityType", "RecommendedTreatmentType", "StatementCondition", diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py index 7e789a578..b1cd40539 100644 --- a/archaeological_finds/models_finds.py +++ b/archaeological_finds/models_finds.py @@ -528,6 +528,40 @@ post_save.connect(post_save_cache, sender=RecommendedTreatmentType) post_delete.connect(post_save_cache, sender=RecommendedTreatmentType) +class RecommendationType(OrderedHierarchicalType): + class Meta: + verbose_name = _("Recommendation type") + verbose_name_plural = _("Recommendation types") + ordering = ( + "parent__order", + "parent__label", + "order", + "label", + ) + ADMIN_SECTION = _("Finds") + + +post_save.connect(post_save_cache, sender=RecommendationType) +post_delete.connect(post_save_cache, sender=RecommendationType) + + +class CurrentStorageConditionType(OrderedHierarchicalType): + class Meta: + verbose_name = _("Current storage condition type") + verbose_name_plural = _("Current storage condition types") + ordering = ( + "parent__order", + "parent__label", + "order", + "label", + ) + ADMIN_SECTION = _("Finds") + + +post_save.connect(post_save_cache, sender=CurrentStorageConditionType) +post_delete.connect(post_save_cache, sender=CurrentStorageConditionType) + + class InventoryMarkingPresence(OrderedType): class Meta: verbose_name = _("Presence of inventory marking type") @@ -2245,6 +2279,8 @@ class Find( "recommended_treatments", "alterations", "alteration_causes", + "recommendations", + "current_storage_conditions", ] GET_VALUES_EXTRA = ValueGetter.GET_VALUES_EXTRA + ["complete_id", "context_record_label"] @@ -2267,6 +2303,8 @@ class Find( "remarkabilities", "technical_areas", "technical_processes", + "recommendations", + "current_storage_conditions", ] CACHED_LABELS = [ "cache_complete_museum_id", @@ -2274,6 +2312,8 @@ class Find( "cached_periods", "cached_object_types", "cached_materials", + "cached_recommendations", + "cached_current_storage_conditions", ] SERIALIZE_CALL = { "base_finds_list": "base_finds_list", @@ -2646,6 +2686,18 @@ class Find( ) insurance_value = models.FloatField(_("Insurance value"), blank=True, null=True) appraisal_date = models.DateField(_("Appraisal date"), blank=True, null=True) + recommendations = models.ManyToManyField( + RecommendationType, + verbose_name=_("Recommendations"), + blank=True, + related_name="finds", + ) + current_storage_conditions = models.ManyToManyField( + CurrentStorageConditionType, + verbose_name=_("Current storage conditions"), + blank=True, + related_name="finds", + ) public_description = models.TextField( _("Public description"), blank=True, default="" ) @@ -2686,6 +2738,18 @@ class Find( default="", help_text=_("Generated automatically - do not edit"), ) + cached_recommendations = models.TextField( + _("Cached recommendations label"), + blank=True, + default="", + help_text=_("Generated automatically - do not edit"), + ) + cached_current_storage_conditions = models.TextField( + _("Cached current storage conditions"), + blank=True, + default="", + help_text=_("Generated automatically - do not edit"), + ) cache_complete_museum_id = models.TextField( _("Complete museum ID"), blank=True, @@ -3628,12 +3692,23 @@ class Find( def _generate_cached_periods(self): return " & ".join([period.label for period in self.periods.all()]) + + def _generate_m2m_label(self, attr): + return " & ".join( + [str(item) for item in getattr(self, attr).all()] + ) def _generate_cached_object_types(self): - return " & ".join([str(obj) for obj in self.object_types.all()]) + return self._generate_m2m_label("object_types") def _generate_cached_materials(self): - return " & ".join([str(mat) for mat in self.material_types.all()]) + return self._generate_m2m_label("material_types") + + def _generate_cached_recommendations(self): + return self._generate_m2m_label("recommendations") + + def _generate_cached_current_storage_conditions(self): + return self._generate_m2m_label("current_storage_conditions") def get_localisation(self, place, is_ref=False): """ diff --git a/archaeological_operations/migrations/0131_archaeologicalsite_other_name.py b/archaeological_operations/migrations/0131_archaeologicalsite_other_name.py new file mode 100644 index 000000000..8dc74646e --- /dev/null +++ b/archaeological_operations/migrations/0131_archaeologicalsite_other_name.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.21 on 2026-06-28 17:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_operations', '0130_archaeologicalsite_set_not_null'), + ] + + operations = [ + migrations.AddField( + model_name='archaeologicalsite', + name='other_name', + field=models.TextField(blank=True, default='', verbose_name='Other name'), + ), + migrations.AddField( + model_name='historicalarchaeologicalsite', + name='other_name', + field=models.TextField(blank=True, default='', verbose_name='Other name'), + ), + ] diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py index 1c6ab4507..eeccad102 100644 --- a/archaeological_operations/models.py +++ b/archaeological_operations/models.py @@ -718,6 +718,7 @@ class ArchaeologicalSite( reference = models.CharField(_("Reference"), max_length=200, unique=True) other_reference = models.TextField(_("Other reference"), blank=True, default="") name = models.CharField(_("Name"), max_length=200, blank=True, default="") + other_name = models.TextField(_("Other name"), blank=True, default="") types = models.ManyToManyField("SiteType", verbose_name=_("Types"), blank=True) periods = models.ManyToManyField(Period, verbose_name=_("Periods"), blank=True) remains = models.ManyToManyField( |
