diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2024-03-08 11:02:06 +0100 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2024-04-16 16:43:02 +0200 |
commit | 16ef679607a95d4e78f3fcbe5e7528e935ef5c8c (patch) | |
tree | 3f7ca2453ef5787fd71111f61179a5fcc4bf41d8 | |
parent | c9731c233ae84841b61a9751cc6140290d101770 (diff) | |
download | Ishtar-16ef679607a95d4e78f3fcbe5e7528e935ef5c8c.tar.bz2 Ishtar-16ef679607a95d4e78f3fcbe5e7528e935ef5c8c.zip |
🏷️ update french states and departments
-rw-r--r-- | ishtar_common/admin.py | 9 | ||||
-rw-r--r-- | ishtar_common/data.py | 23 | ||||
-rw-r--r-- | ishtar_common/management/commands/ishtar_maintenance.py | 18 | ||||
-rw-r--r-- | ishtar_common/migrations/0240_state_number_max_len.py | 36 | ||||
-rw-r--r-- | ishtar_common/migrations/0241_migrate_old_department.py | 50 | ||||
-rw-r--r-- | ishtar_common/models_common.py | 2 | ||||
-rw-r--r-- | ishtar_common/utils.py | 78 |
7 files changed, 163 insertions, 53 deletions
diff --git a/ishtar_common/admin.py b/ishtar_common/admin.py index ae521729d..ae0f9eb3f 100644 --- a/ishtar_common/admin.py +++ b/ishtar_common/admin.py @@ -1196,7 +1196,6 @@ class ImportJSONActionAdmin(admin.ModelAdmin): with open(filename, "wb+") as zipped_file: for chunk in request.FILES["json_file"].chunks(): zipped_file.write(chunk) - result = None result = restore_serialized(filename) try: result = restore_serialized(filename) @@ -1431,7 +1430,7 @@ class CreateAreaForm(forms.Form): area = self.cleaned_data.get("area", 0) if (not area_name and not area) or (area and area_name): raise forms.ValidationError( - _("Choose an area or set an area " "reference.") + _("Choose an area or set an area reference.") ) return self.cleaned_data @@ -1469,8 +1468,10 @@ class CreateDepartmentActionAdmin(GeneralTypeAdmin): form = CreateAreaForm(request.POST) if form.is_valid(): area_name = form.cleaned_data.get("area_name", "") + dpt_num = form.cleaned_data["department_number"] + dpt_num = "0" + str(dpt_num) if dpt_num < 10 else str(dpt_num) if area_name: - slug = "dpt-" + area_name + slug = "dep-" + dpt_num while models.Area.objects.filter(txt_idx=slug).count(): slug += "b" area = models.Area.objects.create(label=area_name, txt_idx=slug) @@ -1479,8 +1480,6 @@ class CreateDepartmentActionAdmin(GeneralTypeAdmin): ) else: area = models.Area.objects.get(id=form.cleaned_data["area"]) - dpt_num = form.cleaned_data["department_number"] - dpt_num = "0" + str(dpt_num) if dpt_num < 10 else str(dpt_num) current_towns = [a.numero_insee for a in area.towns.all()] nb = 0 for town in ( diff --git a/ishtar_common/data.py b/ishtar_common/data.py new file mode 100644 index 000000000..dcbc4aa09 --- /dev/null +++ b/ishtar_common/data.py @@ -0,0 +1,23 @@ +FRENCH_STATES = [ + ("Auvergne-Rhône-Alpe", "FR-ARA", ("01", "03", "07", "15", "26", "38", "42", "43", "63", "69", "73", "74",)), + ("Bourgogne-Franche-Comté", "FR-BFC", ("21", "25", "39", "58", "70", "71", "89", "90",)), + ("Bretagne", "FR-BRE", ("22", "29", "35", "56",)), + ("Centre-Val de Loire", "FR-CVL", ("18", "28", "36", "37", "41", "45",)), + ("Corse", "FR-COR", ("2A", "2B",)), + ("Grand Est", "FR-GES", ("08", "10", "51", "52", "54", "55", "57", "67", "68", "88",)), + ("Hauts-de-France", "FR-HDF", ("02", "59", "60", "62", "80",)), + ("Ile-de-France", "FR-IDF", ("75", "77", "78", "91", "92", "93", "94", "95", )), + ("Normandie", "FR-NOR", ("14", "27", "50", "61", "76",)), + ("Nouvelle-Aquitaine", "FR-NAQ", ("16", "17", "19", "23", "24", "33", "40", "47", "64", "79", "86", "87",)), + ("Occitanie", "FR-OCC", ("09", "11", "12", "30", "31", "32", "34", "46", "48", "65", "66", "81", "82",)), + ("Pays de la Loire", "FR-PDL", ("44", "49", "53", "72", "85",)), + ("Provence Alpes Côte d’Azur", "FR-PAC", ("04", "05", "06", "13", "83", "84",)), +] + +FRENCH_TOM_STATES = [ + ("Guadeloupe", "FR-GUA", []), + ("Guyane", "FR-GUF", []), + ("Martinique", "FR-MTQ", []), + ("La Réunion", "FR-LRE", []), + ("Mayotte", "FR-MAY", []), +] diff --git a/ishtar_common/management/commands/ishtar_maintenance.py b/ishtar_common/management/commands/ishtar_maintenance.py index 8bfd06812..260fbd46c 100644 --- a/ishtar_common/management/commands/ishtar_maintenance.py +++ b/ishtar_common/management/commands/ishtar_maintenance.py @@ -18,6 +18,7 @@ from django.core.management.base import BaseCommand, CommandError from django.template.defaultfilters import slugify from ishtar_common import models_common +from ishtar_common.utils import create_default_areas APPS = ( "ishtar_common", @@ -245,6 +246,11 @@ def task_regenerate_permissions(options): create_permissions(apps.get_app_config(app)) +def task_default_areas(options): + verbose = not options.get("quiet", False) + create_default_areas(verbose=verbose) + + def task_missing_parcels(options): quiet = options.get("quiet", False) Parcel = apps.get_model("archaeological_operations", "Parcel") @@ -286,6 +292,14 @@ def get_filter(filter_str): TASKS = { + "admin_permissions": { + "help": "regenerate basic model permissions", + "action": task_regenerate_permissions, + }, + "admin_default_areas": { + "help": "create default areas from department and states", + "action": task_default_areas, + }, "fix_main_image": { "help": "for items with images and no main image, put the first one created as a main image", "action": task_main_image, @@ -299,10 +313,6 @@ TASKS = { "help": "regenerate cached label", "action": task_check_cached_label, }, - "update_permissions": { - "help": "regenerate basic model permissions", - "action": task_regenerate_permissions, - }, "update_qrcodes": { "help": "regenerate qrcodes", "action": task_regenerate_qrcodes, diff --git a/ishtar_common/migrations/0240_state_number_max_len.py b/ishtar_common/migrations/0240_state_number_max_len.py new file mode 100644 index 000000000..3755035cf --- /dev/null +++ b/ishtar_common/migrations/0240_state_number_max_len.py @@ -0,0 +1,36 @@ +# Generated by Django 2.2.24 on 2024-03-08 10:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ishtar_common', '0239_shootingangle_parent'), + ] + + operations = [ + migrations.AlterModelOptions( + name='language', + options={'verbose_name': 'Language type', 'verbose_name_plural': 'Language types'}, + ), + migrations.AlterModelOptions( + name='shootingangle', + options={'ordering': ('order', 'label'), 'verbose_name': 'Shooting angle type', 'verbose_name_plural': 'Shooting angle types'}, + ), + migrations.AlterField( + model_name='historicalorganization', + name='museum_museofile_id', + field=models.TextField(blank=True, default='', verbose_name='Museofile ID'), + ), + migrations.AlterField( + model_name='organization', + name='museum_museofile_id', + field=models.TextField(blank=True, default='', verbose_name='Museofile ID'), + ), + migrations.AlterField( + model_name='state', + name='number', + field=models.CharField(max_length=10, unique=True, verbose_name='Number'), + ), + ] diff --git a/ishtar_common/migrations/0241_migrate_old_department.py b/ishtar_common/migrations/0241_migrate_old_department.py new file mode 100644 index 000000000..4e5c2432a --- /dev/null +++ b/ishtar_common/migrations/0241_migrate_old_department.py @@ -0,0 +1,50 @@ +# Generated by Django 2.2.24 on 2024-03-07 17:52 + +from django.db import migrations +from django.db.models.functions import Length +from ishtar_common.data import FRENCH_STATES, FRENCH_TOM_STATES + + +def migrate(apps, __): + Area = apps.get_model('ishtar_common', 'Area') + Department = apps.get_model('ishtar_common', 'Department') + State = apps.get_model('ishtar_common', 'State') + Town = apps.get_model('ishtar_common', 'Town') + + if not State.objects.filter(label="Nord-Pas-de-Calais").count(): + # already OK or not french + return + + State.objects.filter(pk__isnull=False).delete() + Area.objects.filter(txt_idx__startswith="dep-").delete() + Area.objects.filter(txt_idx__startswith="state-").delete() + + for lbl, code, departments in (FRENCH_STATES + FRENCH_TOM_STATES): + state = State.objects.create(label=lbl, number=code) + state_area = Area.objects.create(label=lbl, txt_idx=f'state-{code}') + for dep_code in departments: + q = Department.objects.filter(number=dep_code) + if not q.count(): + print(f"{dep_code} department is missing") + continue + dep = q.all()[0] + dep.state = state + dep.save() + dep_area = Area.objects.create(label=dep.label, txt_idx=f'dep-{dep.number}') + dep_area.parent = state_area + dep_area.save() + dep_area.towns.clear() + q2 = Town.objects.annotate(insee_len=Length('numero_insee')).filter( + numero_insee__startswith=dep_code, insee_len=5) + dep_area.towns.add(*list(q2.all())) + + +class Migration(migrations.Migration): + + dependencies = [ + ('ishtar_common', '0240_state_number_max_len'), + ] + + operations = [ + migrations.RunPython(migrate) + ] diff --git a/ishtar_common/models_common.py b/ishtar_common/models_common.py index 8a9de207e..26bc1c63f 100644 --- a/ishtar_common/models_common.py +++ b/ishtar_common/models_common.py @@ -2003,7 +2003,7 @@ class NumberManager(models.Manager): class State(models.Model): label = models.CharField(_("Label"), max_length=30) - number = models.CharField(_("Number"), unique=True, max_length=3) + number = models.CharField(_("Number"), unique=True, max_length=10) objects = NumberManager() class Meta: diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py index 3161e0003..08e7a49b4 100644 --- a/ishtar_common/utils.py +++ b/ishtar_common/utils.py @@ -65,6 +65,7 @@ from django.core.files.storage import FileSystemStorage from django.core.validators import EMPTY_VALUES, MaxValueValidator from django.db import models from django.db.models import Q +from django.db.models.functions import Length from django.http import HttpResponseRedirect from django.urls import reverse, NoReverseMatch from django.utils.crypto import get_random_string @@ -1496,61 +1497,52 @@ def create_default_areas(models=None, verbose=False): areas = {} - idx = 0 - for state in State.objects.all(): - slug = "state-" + slugify(state.label) - area, created = Area.objects.get_or_create( + created = 0 + q = State.objects + total = q.count() + for idx, state in enumerate(q.all()): + if verbose: + sys.stdout.write(f"State \t{idx + 1}/{total}\r") + slug = "state-" + state.number + area, create = Area.objects.get_or_create( txt_idx=slug, defaults={"label": state.label} ) - areas["state-{}".format(state.pk)] = area - if created: - idx += 1 + areas[f"state-{state.pk}"] = area + if create: + created += 1 if verbose: - print("\n* {} state areas added".format(idx)) + sys.stdout.write(f"* {created} state areas added\n") - idx, idx2 = 0, 0 - for dep in Department.objects.all(): - slug = "dep-" + slugify(dep.label) - area, created = Area.objects.get_or_create( + created, association, association2 = 0, 0, 0 + q = Department.objects + total = q.count() + for idx, dep in enumerate(q.all()): + if verbose: + sys.stdout.write(f"Department \t{idx + 1}/{total}\r") + slug = f"dep-{dep.number}" + area, create = Area.objects.get_or_create( txt_idx=slug, defaults={"label": dep.label} ) areas["dep-" + dep.number] = area - if created: - idx += 1 + if create: + created += 1 if not dep.state_id: continue state_slug = "state-{}".format(dep.state_id) - if state_slug not in areas: - continue - if area.parent and area.parent.pk == areas[state_slug].pk: - continue - idx2 += 1 - area.parent = areas[state_slug] - area.save() - if verbose: - print( - "* {} department areas added with {} associations to state".format( - idx, idx2 - ) - ) - - idx = 0 - for town in Town.objects.all(): - if not town.numero_insee or len(town.numero_insee) != 5: - continue - code_dep = "dep-" + town.numero_insee[:2] - code_dep_dom = "dep-" + town.numero_insee[:3] - if code_dep in areas: - if not areas[code_dep].towns.filter(pk=town.pk).count(): - areas[code_dep].towns.add(town) - idx += 1 - elif code_dep_dom in areas: - if not areas[code_dep_dom].towns.filter(pk=town.pk).count(): - areas[code_dep_dom].towns.add(town) - idx += 1 + if state_slug in areas and (not area.parent or area.parent.pk != areas[state_slug].pk): + association += 1 + area.parent = areas[state_slug] + area.save() + area.towns.clear() + q2 = Town.objects.annotate(insee_len=Length('numero_insee')).filter( + numero_insee__startswith=dep.number, insee_len=5) + area.towns.add(*list(q2.all())) if verbose: - print("* {} town associated to department area".format(idx)) + sys.stdout.write( + f"* {created} department areas added with {association} associations to state\n" + ) + sys.stdout.write(f"* {association} town associated to department area") def get_relations_for_graph( |