From 0d1186f97f7e88a19a1576011b5b42fba9778ccd Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Thu, 14 Dec 2023 10:39:20 +0100 Subject: [PATCH 01/26] add load river command --- georiviere/river/management/__init__.py | 0 .../river/management/commands/__init__.py | 0 .../river/management/commands/load_rivers.py | 56 +++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 georiviere/river/management/__init__.py create mode 100644 georiviere/river/management/commands/__init__.py create mode 100644 georiviere/river/management/commands/load_rivers.py diff --git a/georiviere/river/management/__init__.py b/georiviere/river/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/georiviere/river/management/commands/__init__.py b/georiviere/river/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/georiviere/river/management/commands/load_rivers.py b/georiviere/river/management/commands/load_rivers.py new file mode 100644 index 00000000..4bd56e76 --- /dev/null +++ b/georiviere/river/management/commands/load_rivers.py @@ -0,0 +1,56 @@ +from django.contrib.gis.gdal import DataSource +from django.contrib.gis.geos import Point +from django.core.management import BaseCommand +from django.utils.timezone import now +from django.utils.translation import gettext as _ + +from georiviere.description.models import Morphology, Status +from georiviere.river.models import Stream, Topology + + +class Command(BaseCommand): + help = 'Load Rivers' + + def add_arguments(self, parser): + parser.add_argument('file_path', help="File's path to import.") + parser.add_argument('--name-attribute', '-n', action='store', dest='name', default='nom', + help="Name of the name's attribute inside the file") + parser.add_argument('--flush-streams', '-f', action='store_true', dest='flush', default=False, + help="Flush current streams") + parser.add_argument('--default-name-attribute', '-nd', action='store', dest='default_name', default=_('River'), + help="Default name to use if name is empty") + + def handle(self, *args, **options): + file_path = options.get('file_path') + name_column = options.get('name') + default_name = options.get('default_name') + flush = options.get('flush') + data_source = DataSource(file_path) + layer = data_source[0] + total_count = len(layer) + self.stdout.write(f"Load rivers: {total_count} features to import") + count = 0 + if flush: + self.stdout.write(f"Delete streams.....", ending="") + Stream.objects.all().delete() + self.stdout.write(self.style.SUCCESS("done!")) + bulks = [] + for feat in layer: + geom = feat.geom.geos + bulks.append(Stream(geom=geom, + source_location=Point(geom[0]), + name=feat.get(name_column) or default_name)) + count += 1 + if len(bulks) == 100: + objs = Stream.objects.bulk_create(bulks) + # for obj in objs: + # topo = Topology.objects.create(start_position=0, end_position=1, stream=obj) + # Morphology.objects.create(topology=topo, geom=obj.geom) + # topo = Topology.objects.create(start_position=0, end_position=1, stream=obj) + # Status.objects.create(topology=topo, geom=obj.geom) + + bulks = [] + now_2 = now() + self.stdout.write(f"{count} / {total_count}") + + self.stdout.write(f"Morpholgy creation") From 1bdaec9d027a2b516a9e17f416c5139d28664150 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Tue, 19 Dec 2023 10:10:32 +0100 Subject: [PATCH 02/26] use pg triggers --- dev-requirements.txt | 70 ++++++++++++------- docs/changelog.rst | 4 ++ georiviere/altimetry.py | 48 ++++++------- .../migrations/0025_auto_20231215_1124.py | 31 ++++++++ .../migrations/0026_auto_20231218_1222.py | 47 +++++++++++++ georiviere/description/models.py | 4 ++ .../main/management/commands/migrate.py | 11 +-- .../migrations/0004_auto_20231215_1124.py | 19 +++++ .../migrations/0005_auto_20231218_1222.py | 23 ++++++ georiviere/proceeding/models.py | 1 + .../river/management/commands/load_rivers.py | 50 ++++++------- .../migrations/0020_auto_20231215_1020.py | 19 +++++ .../migrations/0021_auto_20231215_1051.py | 23 ++++++ .../migrations/0022_auto_20231215_1052.py | 23 ++++++ .../migrations/0023_auto_20231215_1056.py | 23 ++++++ .../migrations/0024_auto_20231218_1226.py | 27 +++++++ .../migrations/0025_auto_20231218_1325.py | 19 +++++ .../migrations/0026_auto_20231218_1356.py | 23 ++++++ .../migrations/0027_auto_20231218_1400.py | 23 ++++++ .../migrations/0028_auto_20231218_1402.py | 23 ++++++ .../migrations/0029_auto_20231218_1403.py | 23 ++++++ .../migrations/0030_auto_20231218_1405.py | 23 ++++++ .../migrations/0031_auto_20231218_1405.py | 23 ++++++ .../migrations/0032_auto_20231218_1410.py | 19 +++++ .../migrations/0033_auto_20231218_1412.py | 23 ++++++ .../migrations/0034_auto_20231218_1416.py | 23 ++++++ .../migrations/0035_auto_20231218_1418.py | 23 ++++++ .../migrations/0036_auto_20231218_1420.py | 23 ++++++ .../migrations/0037_auto_20231218_1421.py | 23 ++++++ .../migrations/0038_auto_20231218_1431.py | 23 ++++++ .../migrations/0039_auto_20231218_1601.py | 23 ++++++ .../migrations/0040_auto_20231218_1608.py | 23 ++++++ georiviere/river/models.py | 63 +++++++++++++---- georiviere/river/signals.py | 17 +---- georiviere/settings/__init__.py | 1 + requirements.in | 1 + requirements.txt | 5 +- 37 files changed, 756 insertions(+), 114 deletions(-) create mode 100644 georiviere/description/migrations/0025_auto_20231215_1124.py create mode 100644 georiviere/description/migrations/0026_auto_20231218_1222.py create mode 100644 georiviere/proceeding/migrations/0004_auto_20231215_1124.py create mode 100644 georiviere/proceeding/migrations/0005_auto_20231218_1222.py create mode 100644 georiviere/river/migrations/0020_auto_20231215_1020.py create mode 100644 georiviere/river/migrations/0021_auto_20231215_1051.py create mode 100644 georiviere/river/migrations/0022_auto_20231215_1052.py create mode 100644 georiviere/river/migrations/0023_auto_20231215_1056.py create mode 100644 georiviere/river/migrations/0024_auto_20231218_1226.py create mode 100644 georiviere/river/migrations/0025_auto_20231218_1325.py create mode 100644 georiviere/river/migrations/0026_auto_20231218_1356.py create mode 100644 georiviere/river/migrations/0027_auto_20231218_1400.py create mode 100644 georiviere/river/migrations/0028_auto_20231218_1402.py create mode 100644 georiviere/river/migrations/0029_auto_20231218_1403.py create mode 100644 georiviere/river/migrations/0030_auto_20231218_1405.py create mode 100644 georiviere/river/migrations/0031_auto_20231218_1405.py create mode 100644 georiviere/river/migrations/0032_auto_20231218_1410.py create mode 100644 georiviere/river/migrations/0033_auto_20231218_1412.py create mode 100644 georiviere/river/migrations/0034_auto_20231218_1416.py create mode 100644 georiviere/river/migrations/0035_auto_20231218_1418.py create mode 100644 georiviere/river/migrations/0036_auto_20231218_1420.py create mode 100644 georiviere/river/migrations/0037_auto_20231218_1421.py create mode 100644 georiviere/river/migrations/0038_auto_20231218_1431.py create mode 100644 georiviere/river/migrations/0039_auto_20231218_1601.py create mode 100644 georiviere/river/migrations/0040_auto_20231218_1608.py diff --git a/dev-requirements.txt b/dev-requirements.txt index 58b97518..eb2033f4 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,17 +1,19 @@ # -# This file is autogenerated by pip-compile with python 3.9 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: # # pip-compile dev-requirements.in # -alabaster==0.7.12 +alabaster==0.7.13 # via sphinx asgiref==3.3.1 # via # -c requirements.txt # django -babel==2.9.1 +babel==2.14.0 # via sphinx +build==1.0.3 + # via pip-tools certifi==2020.12.5 # via # -c requirements.txt @@ -54,7 +56,7 @@ faker==9.7.1 # via # -c requirements.txt # factory-boy -flake8==4.0.1 +flake8==6.1.0 # via -r dev-requirements.in freezegun==1.1.0 # via @@ -64,8 +66,12 @@ idna==2.10 # via # -c requirements.txt # requests -imagesize==1.3.0 +imagesize==1.4.1 # via sphinx +importlib-metadata==7.0.0 + # via + # build + # sphinx jinja2==2.11.3 # via # -c requirements.txt @@ -74,28 +80,29 @@ markupsafe==1.1.1 # via # -c requirements.txt # jinja2 -mccabe==0.6.1 +mccabe==0.7.0 # via flake8 packaging==20.9 # via # -c requirements.txt + # build # sphinx -pep517==0.12.0 - # via pip-tools -pip-tools==6.5.1 +pip-tools==6.10.0 # via -r dev-requirements.in -pycodestyle==2.8.0 +pycodestyle==2.11.1 # via flake8 -pyflakes==2.4.0 +pyflakes==3.1.0 # via flake8 -pygments==2.15.0 +pygments==2.17.2 # via sphinx -pygraphviz==1.9 +pygraphviz==1.11 # via -r dev-requirements.in pyparsing==2.4.7 # via # -c requirements.txt # packaging +pyproject-hooks==1.0.0 + # via build python-dateutil==2.8.1 # via # -c requirements.txt @@ -104,7 +111,6 @@ python-dateutil==2.8.1 pytz==2021.1 # via # -c requirements.txt - # babel # django requests==2.26.0 # via @@ -116,43 +122,55 @@ six==1.15.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==4.4.0 +sphinx==5.1.1 # via # -r dev-requirements.in # sphinx-rtd-theme -sphinx-rtd-theme==1.0.0 + # sphinxcontrib-applehelp + # sphinxcontrib-devhelp + # sphinxcontrib-htmlhelp + # sphinxcontrib-jquery + # sphinxcontrib-qthelp + # sphinxcontrib-serializinghtml +sphinx-rtd-theme==2.0.0 # via -r dev-requirements.in -sphinxcontrib-applehelp==1.0.2 +sphinxcontrib-applehelp==1.0.7 # via sphinx -sphinxcontrib-devhelp==1.0.2 +sphinxcontrib-devhelp==1.0.5 # via sphinx -sphinxcontrib-htmlhelp==2.0.0 +sphinxcontrib-htmlhelp==2.0.4 # via sphinx +sphinxcontrib-jquery==4.1 + # via sphinx-rtd-theme sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.3 +sphinxcontrib-qthelp==1.0.6 # via sphinx -sphinxcontrib-serializinghtml==1.1.5 +sphinxcontrib-serializinghtml==1.1.9 # via sphinx sqlparse==0.4.1 # via # -c requirements.txt # django # django-debug-toolbar -tblib==1.7.0 +tblib==3.0.0 # via -r dev-requirements.in text-unidecode==1.3 # via # -c requirements.txt # faker -tomli==2.0.0 - # via pep517 +tomli==2.0.1 + # via + # build + # pyproject-hooks urllib3==1.26.3 # via # -c requirements.txt # requests -wheel==0.38.1 +wheel==0.42.0 # via pip-tools +zipp==3.17.0 + # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: # pip diff --git a/docs/changelog.rst b/docs/changelog.rst index 176bd7a2..8c92b620 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,10 @@ CHANGELOG 1.3.0+dev (XXXX-XX-XX) --------------------- +**New features** + +- add load_rivers command + **Bug fix** - Force translation defined in API url /api/portal/ (fix #222) diff --git a/georiviere/altimetry.py b/georiviere/altimetry.py index 64091013..e9b7335f 100644 --- a/georiviere/altimetry.py +++ b/georiviere/altimetry.py @@ -1,33 +1,27 @@ +import pgtrigger from geotrek.altimetry.models import AltimetryMixin as BaseAltimetryMixin -from georiviere.functions import ElevationInfos, Length3D - class AltimetryMixin(BaseAltimetryMixin): class Meta: abstract = True - - def save(self, *args, **kwargs): - super().save(*args, **kwargs) - elevation_infos = self._meta.model.objects.filter(pk=self.pk) \ - .annotate(infos=ElevationInfos('geom')).first().infos - draped_geom = elevation_infos.get('draped') - self.geom_3d = draped_geom - self.slope = elevation_infos.get('slope') - self.min_elevation = elevation_infos.get('min_elevation') - self.max_elevation = elevation_infos.get('max_elevation') - self.ascent = elevation_infos.get('positive_gain') - self.descent = elevation_infos.get('negative_gain') - compute_results = self._meta.model.objects.filter(pk=self.pk) \ - .annotate(length_3d=Length3D(draped_geom)).first() - self.length = compute_results.length_3d - super().save(force_insert=False, - update_fields=[ - 'geom_3d', - 'slope', - 'min_elevation', - 'max_elevation', - 'ascent', - 'descent', - 'length' - ]) + triggers = [ + pgtrigger.Trigger( + name="keep_in_sync", + operation=pgtrigger.UpdateOf('geom') | pgtrigger.Insert, + when=pgtrigger.Before, + declare=[('elevation', 'elevation_infos')], + func=""" + SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation; + -- Update path geometry + NEW.geom_3d := elevation.draped; + NEW.length := ST_3DLength(elevation.draped); + NEW.slope := elevation.slope; + NEW.min_elevation := elevation.min_elevation; + NEW.max_elevation := elevation.max_elevation; + NEW.ascent := elevation.positive_gain; + NEW.descent := elevation.negative_gain; + RETURN NEW; + """ + ) + ] diff --git a/georiviere/description/migrations/0025_auto_20231215_1124.py b/georiviere/description/migrations/0025_auto_20231215_1124.py new file mode 100644 index 00000000..957a97dd --- /dev/null +++ b/georiviere/description/migrations/0025_auto_20231215_1124.py @@ -0,0 +1,31 @@ +# Generated by Django 3.1.14 on 2023-12-15 11:24 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('description', '0024_auto_20230323_1621'), + ] + + operations = [ + pgtrigger.migrations.AddTrigger( + model_name='land', + trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n\n RETURN NEW;\n ', hash='82ffa7255d1e65c383b05ef0fa226da73a7ad6c8', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_fb8bb', table='description_land', when='BEFORE')), + ), + pgtrigger.migrations.AddTrigger( + model_name='morphology', + trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n\n RETURN NEW;\n ', hash='f2e3c5183c820b762d1336a39135727ffc39c5e3', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_472ec', table='description_morphology', when='BEFORE')), + ), + pgtrigger.migrations.AddTrigger( + model_name='status', + trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n\n RETURN NEW;\n ', hash='9ebcbb87cf2196d3c04e0e624571d3a49b1ebb69', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_aa87c', table='description_status', when='BEFORE')), + ), + pgtrigger.migrations.AddTrigger( + model_name='usage', + trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n\n RETURN NEW;\n ', hash='c18fa3553e1c897d5a5e5f3b6cc5836c86429190', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_71b71', table='description_usage', when='BEFORE')), + ), + ] diff --git a/georiviere/description/migrations/0026_auto_20231218_1222.py b/georiviere/description/migrations/0026_auto_20231218_1222.py new file mode 100644 index 00000000..b16732c9 --- /dev/null +++ b/georiviere/description/migrations/0026_auto_20231218_1222.py @@ -0,0 +1,47 @@ +# Generated by Django 3.1.14 on 2023-12-18 12:22 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('description', '0025_auto_20231215_1124'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='land', + name='keep_in_sync', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='morphology', + name='keep_in_sync', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='status', + name='keep_in_sync', + ), + pgtrigger.migrations.RemoveTrigger( + model_name='usage', + name='keep_in_sync', + ), + pgtrigger.migrations.AddTrigger( + model_name='land', + trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n RETURN NEW;\n ', hash='d639f6850243942a05ed1f44f6cf79b88b563bad', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_fb8bb', table='description_land', when='BEFORE')), + ), + pgtrigger.migrations.AddTrigger( + model_name='morphology', + trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n RETURN NEW;\n ', hash='048fe3697643f7682b5336def02a2a9d345947ae', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_472ec', table='description_morphology', when='BEFORE')), + ), + pgtrigger.migrations.AddTrigger( + model_name='status', + trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n RETURN NEW;\n ', hash='967fa66b6c8eb5e17d5bfc49594c2573241d073b', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_aa87c', table='description_status', when='BEFORE')), + ), + pgtrigger.migrations.AddTrigger( + model_name='usage', + trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n RETURN NEW;\n ', hash='69cb0cd06f0dccdca1f09d54169f5a673b87fca5', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_71b71', table='description_usage', when='BEFORE')), + ), + ] diff --git a/georiviere/description/models.py b/georiviere/description/models.py index ca1aaaf2..cd686bb5 100644 --- a/georiviere/description/models.py +++ b/georiviere/description/models.py @@ -199,6 +199,7 @@ class Morphology(AddPropertyBufferMixin, TopologyMixin, TimeStampedModelMixin, class Meta: verbose_name = _("Morphology") verbose_name_plural = _("Morphologies") + triggers = AltimetryMixin.Meta.triggers def __str__(self): if self.main_flow: @@ -268,6 +269,7 @@ class Land(AddPropertyBufferMixin, TimeStampedModelMixin, WatershedPropertiesMix class Meta: verbose_name = _("Land") verbose_name_plural = _("Lands") + triggers = AltimetryMixin.Meta.triggers def __str__(self): return f"{self.land_type}" @@ -306,6 +308,7 @@ class Usage(AddPropertyBufferMixin, TimeStampedModelMixin, WatershedPropertiesMi class Meta: verbose_name = _("Usage") verbose_name_plural = _("Usages") + triggers = AltimetryMixin.Meta.triggers def __str__(self): return ', '.join(self.usage_types.values_list("label", flat=True)) @@ -354,6 +357,7 @@ class Status(TopologyMixin, AddPropertyBufferMixin, TimeStampedModelMixin, Water class Meta: verbose_name = _("Status") verbose_name_plural = _("Statuses") + triggers = AltimetryMixin.Meta.triggers def __str__(self): if self.status_types.count(): diff --git a/georiviere/main/management/commands/migrate.py b/georiviere/main/management/commands/migrate.py index 218fd87a..0219458b 100644 --- a/georiviere/main/management/commands/migrate.py +++ b/georiviere/main/management/commands/migrate.py @@ -21,12 +21,15 @@ class Command(BaseCommand): def handle(self, *args, **options): check_srid_has_meter_unit() # set_search_path() - for app in apps.get_app_configs(): - # move_models_to_schemas(app) - load_sql_files(app, 'pre') + # for app in apps.get_app_configs(): + # # move_models_to_schemas(app) + # load_sql_files(app, 'pre') super().handle(*args, **options) for app in apps.get_app_configs(): # move_models_to_schemas(app) - load_sql_files(app, 'post') + try: + load_sql_files(app, 'post') + except Exception: + pass call_command('sync_translation_fields', '--noinput') call_command('update_translation_fields') diff --git a/georiviere/proceeding/migrations/0004_auto_20231215_1124.py b/georiviere/proceeding/migrations/0004_auto_20231215_1124.py new file mode 100644 index 00000000..01a23413 --- /dev/null +++ b/georiviere/proceeding/migrations/0004_auto_20231215_1124.py @@ -0,0 +1,19 @@ +# Generated by Django 3.1.14 on 2023-12-15 11:24 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('proceeding', '0003_auto_20210804_1014'), + ] + + operations = [ + pgtrigger.migrations.AddTrigger( + model_name='proceeding', + trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n\n RETURN NEW;\n ', hash='4580ed3c25a4cd5a156ff3a0c1efd6c8301d8e25', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_6ba14', table='proceeding_proceeding', when='BEFORE')), + ), + ] diff --git a/georiviere/proceeding/migrations/0005_auto_20231218_1222.py b/georiviere/proceeding/migrations/0005_auto_20231218_1222.py new file mode 100644 index 00000000..5a7e4ac6 --- /dev/null +++ b/georiviere/proceeding/migrations/0005_auto_20231218_1222.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-18 12:22 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('proceeding', '0004_auto_20231215_1124'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='proceeding', + name='keep_in_sync', + ), + pgtrigger.migrations.AddTrigger( + model_name='proceeding', + trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n RETURN NEW;\n ', hash='8be1e3d34cf0ef421d9f1750b10e7ef296d6a20d', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_6ba14', table='proceeding_proceeding', when='BEFORE')), + ), + ] diff --git a/georiviere/proceeding/models.py b/georiviere/proceeding/models.py index ab6627a3..c88520b7 100644 --- a/georiviere/proceeding/models.py +++ b/georiviere/proceeding/models.py @@ -49,6 +49,7 @@ def get_create_label(cls): class Meta: verbose_name = _("Proceeding") verbose_name_plural = _("Proceedings") + triggers = AltimetryMixin.Meta.triggers class Event(models.Model): diff --git a/georiviere/river/management/commands/load_rivers.py b/georiviere/river/management/commands/load_rivers.py index 4bd56e76..eca252d8 100644 --- a/georiviere/river/management/commands/load_rivers.py +++ b/georiviere/river/management/commands/load_rivers.py @@ -1,11 +1,11 @@ +from itertools import islice + from django.contrib.gis.gdal import DataSource from django.contrib.gis.geos import Point from django.core.management import BaseCommand -from django.utils.timezone import now from django.utils.translation import gettext as _ -from georiviere.description.models import Morphology, Status -from georiviere.river.models import Stream, Topology +from georiviere.river.models import Stream class Command(BaseCommand): @@ -14,11 +14,11 @@ class Command(BaseCommand): def add_arguments(self, parser): parser.add_argument('file_path', help="File's path to import.") parser.add_argument('--name-attribute', '-n', action='store', dest='name', default='nom', - help="Name of the name's attribute inside the file") + help="Attribute name in file to use as river name") parser.add_argument('--flush-streams', '-f', action='store_true', dest='flush', default=False, help="Flush current streams") parser.add_argument('--default-name-attribute', '-nd', action='store', dest='default_name', default=_('River'), - help="Default name to use if name is empty") + help="Default name to use if attribute name specified is empty") def handle(self, *args, **options): file_path = options.get('file_path') @@ -29,28 +29,24 @@ def handle(self, *args, **options): layer = data_source[0] total_count = len(layer) self.stdout.write(f"Load rivers: {total_count} features to import") - count = 0 if flush: - self.stdout.write(f"Delete streams.....", ending="") + self.stdout.write("Delete streams.....", ending="") Stream.objects.all().delete() self.stdout.write(self.style.SUCCESS("done!")) - bulks = [] - for feat in layer: - geom = feat.geom.geos - bulks.append(Stream(geom=geom, - source_location=Point(geom[0]), - name=feat.get(name_column) or default_name)) - count += 1 - if len(bulks) == 100: - objs = Stream.objects.bulk_create(bulks) - # for obj in objs: - # topo = Topology.objects.create(start_position=0, end_position=1, stream=obj) - # Morphology.objects.create(topology=topo, geom=obj.geom) - # topo = Topology.objects.create(start_position=0, end_position=1, stream=obj) - # Status.objects.create(topology=topo, geom=obj.geom) - - bulks = [] - now_2 = now() - self.stdout.write(f"{count} / {total_count}") - - self.stdout.write(f"Morpholgy creation") + + batch_size = 100 + + objs = (Stream(geom=feat.geom.geos, + source_location=Point(feat.geom.geos[0]), + name=feat.get(name_column) or default_name) for feat in layer) + count = 0 + while True: + batch = list(islice(objs, batch_size)) + count += len(batch) + if not batch: + break + self.stdout.write(f"{count} / {total_count}", ending="") + Stream.objects.bulk_create(batch, batch_size) + self.stdout.write(self.style.SUCCESS(" ok!")) + + self.stdout.write(self.style.SUCCESS(f"Successfully import {total_count} rivers and associated morphologies / status")) diff --git a/georiviere/river/migrations/0020_auto_20231215_1020.py b/georiviere/river/migrations/0020_auto_20231215_1020.py new file mode 100644 index 00000000..e5421117 --- /dev/null +++ b/georiviere/river/migrations/0020_auto_20231215_1020.py @@ -0,0 +1,19 @@ +# Generated by Django 3.1.14 on 2023-12-15 10:20 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0019_stream_description'), + ] + + operations = [ + pgtrigger.migrations.AddTrigger( + model_name='stream', + trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation JSONB;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n RETURN NEW;\n ', hash='6c62fd64699ff351273ae8753db0b43dd5defaf7', operation='UPDATE OR INSERT', pgid='pgtrigger_keep_in_sync_7a86b', table='river_stream', when='BEFORE')), + ), + ] diff --git a/georiviere/river/migrations/0021_auto_20231215_1051.py b/georiviere/river/migrations/0021_auto_20231215_1051.py new file mode 100644 index 00000000..bd951d1f --- /dev/null +++ b/georiviere/river/migrations/0021_auto_20231215_1051.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-15 10:51 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0020_auto_20231215_1020'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='stream', + name='keep_in_sync', + ), + pgtrigger.migrations.AddTrigger( + model_name='stream', + trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := element.draped;\n NEW.length := ST_3DLength(element.draped);\n NEW.slope := element.slope;\n NEW.min_elevation := element.min_elevation;\n NEW.max_elevation := element.max_elevation;\n NEW.ascent := element.positive_gain;\n NEW.descent := element.negative_gain;\n\n RETURN NEW;\n ', hash='fdeef3b3432dda345b1ec896b91e84eb120a9986', operation='UPDATE OR INSERT', pgid='pgtrigger_keep_in_sync_7a86b', table='river_stream', when='BEFORE')), + ), + ] diff --git a/georiviere/river/migrations/0022_auto_20231215_1052.py b/georiviere/river/migrations/0022_auto_20231215_1052.py new file mode 100644 index 00000000..9a4e0b26 --- /dev/null +++ b/georiviere/river/migrations/0022_auto_20231215_1052.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-15 10:52 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0021_auto_20231215_1051'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='stream', + name='keep_in_sync', + ), + pgtrigger.migrations.AddTrigger( + model_name='stream', + trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n\n RETURN NEW;\n ', hash='24de00d1e6f9be9e088db3410e54b0de328653a3', operation='UPDATE OR INSERT', pgid='pgtrigger_keep_in_sync_7a86b', table='river_stream', when='BEFORE')), + ), + ] diff --git a/georiviere/river/migrations/0023_auto_20231215_1056.py b/georiviere/river/migrations/0023_auto_20231215_1056.py new file mode 100644 index 00000000..6e669b8a --- /dev/null +++ b/georiviere/river/migrations/0023_auto_20231215_1056.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-15 10:56 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0022_auto_20231215_1052'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='stream', + name='keep_in_sync', + ), + pgtrigger.migrations.AddTrigger( + model_name='stream', + trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n\n RETURN NEW;\n ', hash='168b84532fa3b4230f53fbd1cfdb1169c5d72a0a', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_7a86b', table='river_stream', when='BEFORE')), + ), + ] diff --git a/georiviere/river/migrations/0024_auto_20231218_1226.py b/georiviere/river/migrations/0024_auto_20231218_1226.py new file mode 100644 index 00000000..4d4f21a1 --- /dev/null +++ b/georiviere/river/migrations/0024_auto_20231218_1226.py @@ -0,0 +1,27 @@ +# Generated by Django 3.1.14 on 2023-12-18 12:26 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0023_auto_20231215_1056'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='stream', + name='keep_in_sync', + ), + pgtrigger.migrations.AddTrigger( + model_name='stream', + trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n RETURN NEW;\n ', hash='e66f827b3e0e2d3e5f822a259752f2d8a48a7c26', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_7a86b', table='river_stream', when='BEFORE')), + ), + pgtrigger.migrations.AddTrigger( + model_name='topology', + trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos; geom geometry;', func='\n IF (NEW.start_point != OLD.start_point OR NEW.end_point != OLD.end_point) THEN \n SELECT geom FROM river_stream r WHERE NEW.id = r.id INTO geom;\n UPDATE description_morphology\n SET geom = ST_LINESUBSTRING(geom, NEW.START_POINT, NEW.END_POINT)\n WHERE topology_id = NEW.id; \n UPDATE description_status\n SET geom = ST_LINESUBSTRING(geom, NEW.START_POINT, NEW.END_POINT)\n WHERE topology_id = NEW.id; \n END IF;\n RETURN NEW;\n ', hash='db1df9343d9079232a59df61b34bfcd7bc2df48a', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='BEFORE')), + ), + ] diff --git a/georiviere/river/migrations/0025_auto_20231218_1325.py b/georiviere/river/migrations/0025_auto_20231218_1325.py new file mode 100644 index 00000000..74c03ca5 --- /dev/null +++ b/georiviere/river/migrations/0025_auto_20231218_1325.py @@ -0,0 +1,19 @@ +# Generated by Django 3.1.14 on 2023-12-18 13:25 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0024_auto_20231218_1226'), + ] + + operations = [ + pgtrigger.migrations.AddTrigger( + model_name='stream', + trigger=pgtrigger.compiler.Trigger(name='create_topologies', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE topology_morphology integer; topology_status integer;', func='\n INSERT INTO river_topology (stream_id, start_position, end_position)\n VALUES (NEW.id, 0, 1) RETURNING id INTO topology_morphology;\n INSERT INTO description_morphology (topology_id, geom) VALUES (topology_morphology, NEW.geom);\n INSERT INTO river_topology (stream_id, start_position, end_position)\n VALUES (NEW.id, 0, 1) RETURNING id INTO topology_status;\n INSERT INTO description_status (topology_id, geom) VALUES (topology_status, NEW.geom);\n RETURN NEW;\n ', hash='c0b7e1615c64b92e36e49803f3001ebde7dd517e', operation='INSERT', pgid='pgtrigger_create_topologies_e8d7d', table='river_stream', when='AFTER')), + ), + ] diff --git a/georiviere/river/migrations/0026_auto_20231218_1356.py b/georiviere/river/migrations/0026_auto_20231218_1356.py new file mode 100644 index 00000000..45b90ad4 --- /dev/null +++ b/georiviere/river/migrations/0026_auto_20231218_1356.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-18 13:56 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0025_auto_20231218_1325'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='topology', + name='update_topology_geom', + ), + pgtrigger.migrations.AddTrigger( + model_name='topology', + trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos; geom geometry;', func='\n IF (NEW.start_position != OLD.start_position OR NEW.end_position != OLD.end_position) THEN \n SELECT geom FROM river_stream r WHERE NEW.id = r.id INTO geom;\n UPDATE description_morphology\n SET geom = ST_LINESUBSTRING(geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n UPDATE description_status\n SET geom = ST_LINESUBSTRING(geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n END IF;\n RETURN NEW;\n ', hash='10d2e4894631bee97f91deeb607004d3a5295448', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='BEFORE')), + ), + ] diff --git a/georiviere/river/migrations/0027_auto_20231218_1400.py b/georiviere/river/migrations/0027_auto_20231218_1400.py new file mode 100644 index 00000000..f32c8f08 --- /dev/null +++ b/georiviere/river/migrations/0027_auto_20231218_1400.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-18 14:00 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0026_auto_20231218_1356'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='stream', + name='create_topologies', + ), + pgtrigger.migrations.AddTrigger( + model_name='stream', + trigger=pgtrigger.compiler.Trigger(name='create_topologies', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE topology_morphology integer; topology_status integer;', func='\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_morphology;\n INSERT INTO description_morphology (topology_id, geom) VALUES (topology_morphology, NEW.geom);\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_status;\n INSERT INTO description_status (topology_id, geom) VALUES (topology_status, NEW.geom);\n RETURN NEW;\n ', hash='4ebe61234dd666bf424de96761a8af7e0a72560f', operation='INSERT', pgid='pgtrigger_create_topologies_e8d7d', table='river_stream', when='AFTER')), + ), + ] diff --git a/georiviere/river/migrations/0028_auto_20231218_1402.py b/georiviere/river/migrations/0028_auto_20231218_1402.py new file mode 100644 index 00000000..227b45d4 --- /dev/null +++ b/georiviere/river/migrations/0028_auto_20231218_1402.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-18 14:02 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0027_auto_20231218_1400'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='stream', + name='create_topologies', + ), + pgtrigger.migrations.AddTrigger( + model_name='stream', + trigger=pgtrigger.compiler.Trigger(name='create_topologies', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE topology_morphology integer; topology_status integer;', func='\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_morphology;\n INSERT INTO description_morphology (topology_id, geom, date_insert, date_update) VALUES (topology_morphology, NEW.geom, NOW(), NOW());\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_status;\n INSERT INTO description_status (topology_id, geom, date_insert, date_update) VALUES (topology_status, NEW.geom, NOW(), NOW());\n RETURN NEW;\n ', hash='606f9274946baa820c7792e04a1f6559948a2e8e', operation='INSERT', pgid='pgtrigger_create_topologies_e8d7d', table='river_stream', when='AFTER')), + ), + ] diff --git a/georiviere/river/migrations/0029_auto_20231218_1403.py b/georiviere/river/migrations/0029_auto_20231218_1403.py new file mode 100644 index 00000000..8416c313 --- /dev/null +++ b/georiviere/river/migrations/0029_auto_20231218_1403.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-18 14:03 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0028_auto_20231218_1402'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='stream', + name='create_topologies', + ), + pgtrigger.migrations.AddTrigger( + model_name='stream', + trigger=pgtrigger.compiler.Trigger(name='create_topologies', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE topology_morphology integer; topology_status integer;', func="\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_morphology;\n INSERT INTO description_morphology (topology_id, geom, description, date_insert, date_update)\n VALUES (topology_morphology, NEW.geom, '', NOW(), NOW());\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_status;\n INSERT INTO description_status (topology_id, geom, date_insert, date_update) VALUES (topology_status, NEW.geom, NOW(), NOW());\n RETURN NEW;\n ", hash='cfb353801531d9e2c134a09c85d8a69807704a71', operation='INSERT', pgid='pgtrigger_create_topologies_e8d7d', table='river_stream', when='AFTER')), + ), + ] diff --git a/georiviere/river/migrations/0030_auto_20231218_1405.py b/georiviere/river/migrations/0030_auto_20231218_1405.py new file mode 100644 index 00000000..1ef79185 --- /dev/null +++ b/georiviere/river/migrations/0030_auto_20231218_1405.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-18 14:05 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0029_auto_20231218_1403'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='stream', + name='create_topologies', + ), + pgtrigger.migrations.AddTrigger( + model_name='stream', + trigger=pgtrigger.compiler.Trigger(name='create_topologies', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE topology_morphology integer; topology_status integer;', func="\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_morphology;\n INSERT INTO description_morphology (topology_id, geom, description, date_insert, date_update)\n VALUES (topology_morphology, NEW.geom, '', NOW(), NOW());\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_status;\n INSERT INTO description_status (topology_id, geom, regulation, referencial, descrption, date_insert, date_update)\n VALUES (topology_status, NEW.geom, FALSE, FALSE, '', NOW(), NOW());\n RETURN NEW;\n ", hash='f5c7079e6d4e21c67d642ea14d61d4e2f39787b0', operation='INSERT', pgid='pgtrigger_create_topologies_e8d7d', table='river_stream', when='AFTER')), + ), + ] diff --git a/georiviere/river/migrations/0031_auto_20231218_1405.py b/georiviere/river/migrations/0031_auto_20231218_1405.py new file mode 100644 index 00000000..2dbd1031 --- /dev/null +++ b/georiviere/river/migrations/0031_auto_20231218_1405.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-18 14:05 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0030_auto_20231218_1405'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='stream', + name='create_topologies', + ), + pgtrigger.migrations.AddTrigger( + model_name='stream', + trigger=pgtrigger.compiler.Trigger(name='create_topologies', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE topology_morphology integer; topology_status integer;', func="\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_morphology;\n INSERT INTO description_morphology (topology_id, geom, description, date_insert, date_update)\n VALUES (topology_morphology, NEW.geom, '', NOW(), NOW());\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_status;\n INSERT INTO description_status (topology_id, geom, regulation, referencial, description, date_insert, date_update)\n VALUES (topology_status, NEW.geom, FALSE, FALSE, '', NOW(), NOW());\n RETURN NEW;\n ", hash='e846f76834647fd2338681a9530765b6d1883cc9', operation='INSERT', pgid='pgtrigger_create_topologies_e8d7d', table='river_stream', when='AFTER')), + ), + ] diff --git a/georiviere/river/migrations/0032_auto_20231218_1410.py b/georiviere/river/migrations/0032_auto_20231218_1410.py new file mode 100644 index 00000000..1e19b353 --- /dev/null +++ b/georiviere/river/migrations/0032_auto_20231218_1410.py @@ -0,0 +1,19 @@ +# Generated by Django 3.1.14 on 2023-12-18 14:10 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0031_auto_20231218_1405'), + ] + + operations = [ + pgtrigger.migrations.AddTrigger( + model_name='stream', + trigger=pgtrigger.compiler.Trigger(name='update_topologies', sql=pgtrigger.compiler.UpsertTriggerSql(func='\n UPDATE river_topology SET start_position=start_position WHERE stream_id=NEW.id;\n RETURN NEW;\n ', hash='0b6322b6b455eed7b6a2a78c79b07e08e9a86611', operation='UPDATE OF "geom"', pgid='pgtrigger_update_topologies_6ab45', table='river_stream', when='AFTER')), + ), + ] diff --git a/georiviere/river/migrations/0033_auto_20231218_1412.py b/georiviere/river/migrations/0033_auto_20231218_1412.py new file mode 100644 index 00000000..1b5d52e2 --- /dev/null +++ b/georiviere/river/migrations/0033_auto_20231218_1412.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-18 14:12 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0032_auto_20231218_1410'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='topology', + name='update_topology_geom', + ), + pgtrigger.migrations.AddTrigger( + model_name='topology', + trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos; geom geometry;', func='\n SELECT geom FROM river_stream r WHERE NEW.id = r.id INTO geom;\n UPDATE description_morphology\n SET geom = ST_LINESUBSTRING(geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n UPDATE description_status\n SET geom = ST_LINESUBSTRING(geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n RETURN NEW;\n ', hash='2b83b20dab6aa7e5456c1e10694f527dc98eb281', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='BEFORE')), + ), + ] diff --git a/georiviere/river/migrations/0034_auto_20231218_1416.py b/georiviere/river/migrations/0034_auto_20231218_1416.py new file mode 100644 index 00000000..653b8de5 --- /dev/null +++ b/georiviere/river/migrations/0034_auto_20231218_1416.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-18 14:16 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0033_auto_20231218_1412'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='topology', + name='update_topology_geom', + ), + pgtrigger.migrations.AddTrigger( + model_name='topology', + trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos; geom geometry;', func='\n SELECT r.geom FROM river_stream r WHERE NEW.id = r.id INTO geom;\n UPDATE description_morphology\n SET geom = ST_LINESUBSTRING(geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n UPDATE description_status\n SET geom = ST_LINESUBSTRING(geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n RETURN NEW;\n ', hash='1e3e1dbd526ffd01e8155aec62fad614e188471d', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='BEFORE')), + ), + ] diff --git a/georiviere/river/migrations/0035_auto_20231218_1418.py b/georiviere/river/migrations/0035_auto_20231218_1418.py new file mode 100644 index 00000000..e92cd864 --- /dev/null +++ b/georiviere/river/migrations/0035_auto_20231218_1418.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-18 14:18 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0034_auto_20231218_1416'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='topology', + name='update_topology_geom', + ), + pgtrigger.migrations.AddTrigger( + model_name='topology', + trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos; geom geometry;', func='\n SELECT r.geom FROM river_stream r WHERE NEW.id = r.id INTO geom;\n UPDATE description_morphology m\n SET m.geom = ST_LINESUBSTRING(geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n UPDATE description_status s\n SET s.geom = ST_LINESUBSTRING(geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n RETURN NEW;\n ', hash='a3d43086e66e04cde5bf979df1f4565a3bb9e791', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='BEFORE')), + ), + ] diff --git a/georiviere/river/migrations/0036_auto_20231218_1420.py b/georiviere/river/migrations/0036_auto_20231218_1420.py new file mode 100644 index 00000000..4421a74f --- /dev/null +++ b/georiviere/river/migrations/0036_auto_20231218_1420.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-18 14:20 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0035_auto_20231218_1418'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='topology', + name='update_topology_geom', + ), + pgtrigger.migrations.AddTrigger( + model_name='topology', + trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos; stream_geom geometry;', func='\n SELECT r.geom FROM river_stream r WHERE NEW.id = r.id INTO stream_geom;\n UPDATE description_morphology m\n SET m.geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n UPDATE description_status s\n SET s.geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n RETURN NEW;\n ', hash='1671ae29035c32a992993d3518965e8e9c0a605f', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='BEFORE')), + ), + ] diff --git a/georiviere/river/migrations/0037_auto_20231218_1421.py b/georiviere/river/migrations/0037_auto_20231218_1421.py new file mode 100644 index 00000000..1739897b --- /dev/null +++ b/georiviere/river/migrations/0037_auto_20231218_1421.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-18 14:21 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0036_auto_20231218_1420'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='topology', + name='update_topology_geom', + ), + pgtrigger.migrations.AddTrigger( + model_name='topology', + trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos; stream_geom geometry;', func='\n SELECT r.geom FROM river_stream r WHERE NEW.id = r.id INTO stream_geom;\n UPDATE description_morphology\n SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n UPDATE description_status\n SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n RETURN NEW;\n ', hash='444948eb36585ca5ea4dfdad5e9be32137e67844', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='BEFORE')), + ), + ] diff --git a/georiviere/river/migrations/0038_auto_20231218_1431.py b/georiviere/river/migrations/0038_auto_20231218_1431.py new file mode 100644 index 00000000..26019979 --- /dev/null +++ b/georiviere/river/migrations/0038_auto_20231218_1431.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-18 14:31 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0037_auto_20231218_1421'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='topology', + name='update_topology_geom', + ), + pgtrigger.migrations.AddTrigger( + model_name='topology', + trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE stream_geom geometry;', func='\n SELECT r.geom FROM river_stream r WHERE NEW.id = r.id INTO stream_geom;\n UPDATE description_morphology\n SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n UPDATE description_status\n SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n RETURN NEW;\n ', hash='f0a3386a26d41f8268db5bbdb554ba4cc3ae1612', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='AFTER')), + ), + ] diff --git a/georiviere/river/migrations/0039_auto_20231218_1601.py b/georiviere/river/migrations/0039_auto_20231218_1601.py new file mode 100644 index 00000000..06a328cb --- /dev/null +++ b/georiviere/river/migrations/0039_auto_20231218_1601.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-18 16:01 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0038_auto_20231218_1431'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='stream', + name='update_topologies', + ), + pgtrigger.migrations.AddTrigger( + model_name='stream', + trigger=pgtrigger.compiler.Trigger(name='update_topologies', sql=pgtrigger.compiler.UpsertTriggerSql(func='\n UPDATE river_topology SET id=id WHERE stream_id=NEW.id;\n RETURN NEW;\n ', hash='704192b93012d12fa95b06b03618981a49609a4e', operation='UPDATE OF "geom"', pgid='pgtrigger_update_topologies_6ab45', table='river_stream', when='AFTER')), + ), + ] diff --git a/georiviere/river/migrations/0040_auto_20231218_1608.py b/georiviere/river/migrations/0040_auto_20231218_1608.py new file mode 100644 index 00000000..ad4c8f4d --- /dev/null +++ b/georiviere/river/migrations/0040_auto_20231218_1608.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-18 16:08 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0039_auto_20231218_1601'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='topology', + name='update_topology_geom', + ), + pgtrigger.migrations.AddTrigger( + model_name='topology', + trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE stream_geom geometry;', func='\n SELECT r.geom FROM river_stream r WHERE NEW.stream_id = r.id INTO stream_geom;\n UPDATE description_morphology\n SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n UPDATE description_status\n SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n RETURN NEW;\n ', hash='4d63b6e0ef200235882742af37d834d00b5a271a', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='AFTER')), + ), + ] diff --git a/georiviere/river/models.py b/georiviere/river/models.py index 41f37cbd..9283a84c 100644 --- a/georiviere/river/models.py +++ b/georiviere/river/models.py @@ -1,3 +1,4 @@ +import pgtrigger from django.conf import settings from django.contrib.contenttypes.models import ContentType from django.contrib.gis.db import models @@ -19,7 +20,7 @@ from georiviere.main.models import AddPropertyBufferMixin from georiviere.altimetry import AltimetryMixin from georiviere.finances_administration.models import AdministrativeFile -from georiviere.functions import ClosestPoint, LineSubString +from georiviere.functions import ClosestPoint from georiviere.knowledge.models import Knowledge, FollowUp from georiviere.main.models import DistanceToSource from georiviere.observations.models import Station @@ -96,6 +97,37 @@ class FlowChoices(models.IntegerChoices): class Meta: verbose_name = _("Stream") verbose_name_plural = _("Streams") + triggers = AltimetryMixin.Meta.triggers + [ + pgtrigger.Trigger( + name="create_topologies", + operation=pgtrigger.Insert, + declare=[ + ('topology_morphology', 'integer'), + ('topology_status', 'integer') + ], + when=pgtrigger.After, + func=""" + INSERT INTO river_topology (stream_id, start_position, end_position, qualified) + VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_morphology; + INSERT INTO description_morphology (topology_id, geom, description, date_insert, date_update) + VALUES (topology_morphology, NEW.geom, '', NOW(), NOW()); + INSERT INTO river_topology (stream_id, start_position, end_position, qualified) + VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_status; + INSERT INTO description_status (topology_id, geom, regulation, referencial, description, date_insert, date_update) + VALUES (topology_status, NEW.geom, FALSE, FALSE, '', NOW(), NOW()); + RETURN NEW; + """ + ), + pgtrigger.Trigger( + name="update_topologies", + operation=pgtrigger.UpdateOf('geom'), + when=pgtrigger.After, + func=""" + UPDATE river_topology SET id=id WHERE stream_id=NEW.id; + RETURN NEW; + """ + ) + ] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -216,21 +248,26 @@ def __str__(self): else: return _("Topology {}").format(self.pk) - def save(self, *args, **kwargs): - super().save(*args, **kwargs) - geom_topology = self._meta.model.objects.filter(pk=self.pk) \ - .annotate(substring=LineSubString(self.stream.geom, self.start_position, self.end_position)).first().substring - if hasattr(self, 'status'): - self.status.geom = geom_topology - self.status.save() - elif hasattr(self, 'morphology'): - self.morphology.geom = geom_topology - self.morphology.save() - super().save(force_insert=False) - class Meta: verbose_name = _("Topology") verbose_name_plural = _("Topologies") + triggers = [ + pgtrigger.Trigger( + name="update_topology_geom", + operation=pgtrigger.Update | pgtrigger.Insert, + when=pgtrigger.After, + declare=[('stream_geom', 'geometry')], + func=""" + SELECT r.geom FROM river_stream r WHERE NEW.stream_id = r.id INTO stream_geom; + UPDATE description_morphology + SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position) + WHERE topology_id = NEW.id; + UPDATE description_status + SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position) + WHERE topology_id = NEW.id; + RETURN NEW; + """ + )] Study.add_property('stations', Station.within_buffer, _("Stations")) diff --git a/georiviere/river/signals.py b/georiviere/river/signals.py index 77e46a0e..3be48afa 100644 --- a/georiviere/river/signals.py +++ b/georiviere/river/signals.py @@ -3,33 +3,18 @@ from django.contrib.contenttypes.models import ContentType from django.contrib.gis.db.models.functions import Distance, Length, LineLocatePoint from django.db.models.signals import post_save -from django.db.models.fields.reverse_related import OneToOneRel from django.db.models import F, FloatField, Case, When from django.dispatch import receiver from georiviere.functions import ClosestPoint, LineSubString from georiviere.main.models import DistanceToSource -from georiviere.river.models import Stream, Topology, TopologyMixin +from georiviere.river.models import Stream, TopologyMixin from mapentity.models import MapEntityMixin -@receiver(post_save, sender=Stream) -def save_stream(sender, instance, **kwargs): - if kwargs['created']: - class_topos = [field.related_model for field in instance.topologies.model._meta.get_fields() - if isinstance(field, OneToOneRel)] - for class_topo in class_topos: - topology = Topology.objects.create(start_position=0, end_position=1, stream=instance) - class_topo.objects.create(topology=topology, geom=instance.geom) - else: - for topology in instance.topologies.all(): - topology.save() - - @receiver(post_save, sender=Stream) def save_stream_generate_distance_to_source(sender, instance, **kwargs): - for model in apps.get_models(): if issubclass(model, MapEntityMixin) and not issubclass(model, TopologyMixin) and model != Stream and 'geom' in [field.name for field in model._meta.get_fields()]: distances_to_sources = [] diff --git a/georiviere/settings/__init__.py b/georiviere/settings/__init__.py index 4daf8d0f..00e4741c 100644 --- a/georiviere/settings/__init__.py +++ b/georiviere/settings/__init__.py @@ -135,6 +135,7 @@ def construct_relative_path_mock(current_template_name, relative_name): 'embed_video', 'djgeojson', 'django_filters', + 'pgtrigger', 'compressor', 'mapentity', # mapentity should be placed after app declaring paperclip models 'leaflet', diff --git a/requirements.in b/requirements.in index a4d9353d..c09d1eb1 100644 --- a/requirements.in +++ b/requirements.in @@ -14,6 +14,7 @@ sentry-sdk django-admin-ordering djangorestframework-camel-case jsonschema +django-pgtrigger # Use until latest version of geotrek (> 2.99.0) drf-spectacular diff --git a/requirements.txt b/requirements.txt index b6af05d8..34e85eab 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.10 +# This file is autogenerated by pip-compile with Python 3.9 # by the following command: # # pip-compile @@ -91,6 +91,7 @@ django==3.1.14 # django-leaflet # django-modeltranslation # django-mptt + # django-pgtrigger # django-querysetsequence # django-weasyprint # djangorestframework @@ -144,6 +145,8 @@ django-modeltranslation==0.17.3 # via mapentity django-mptt==0.11.0 # via geotrek +django-pgtrigger==4.11.0 + # via -r requirements.in django-querysetsequence==0.14 # via django-autocomplete-light django-tinymce==2.9.0 From d32ed9219a522a2d94ea7457c9ed292324d102ab Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Tue, 19 Dec 2023 10:32:17 +0100 Subject: [PATCH 03/26] use pg triggers --- .../migrations/0041_auto_20231219_0932.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 georiviere/river/migrations/0041_auto_20231219_0932.py diff --git a/georiviere/river/migrations/0041_auto_20231219_0932.py b/georiviere/river/migrations/0041_auto_20231219_0932.py new file mode 100644 index 00000000..12429cd4 --- /dev/null +++ b/georiviere/river/migrations/0041_auto_20231219_0932.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.14 on 2023-12-19 09:32 + +from django.db import migrations +import pgtrigger.compiler +import pgtrigger.migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('river', '0040_auto_20231218_1608'), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name='topology', + name='update_topology_geom', + ), + pgtrigger.migrations.AddTrigger( + model_name='topology', + trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE stream_geom geometry;', func='\n SELECT r.geom FROM river_stream r WHERE NEW.stream_id = r.id INTO stream_geom;\n UPDATE description_morphology\n SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id;\n UPDATE description_status\n SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id;\n RETURN NEW;\n ', hash='0d8dce1088e59bd290e9ffe0d6bfb8a2493a5c1c', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='AFTER')), + ), + ] From fa5fcce78981b5b7a6f5c599987b1142644d0d06 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Tue, 19 Dec 2023 10:40:38 +0100 Subject: [PATCH 04/26] use pg triggers --- georiviere/river/templates/river/sql/pre_types.sql | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 georiviere/river/templates/river/sql/pre_types.sql diff --git a/georiviere/river/templates/river/sql/pre_types.sql b/georiviere/river/templates/river/sql/pre_types.sql new file mode 100644 index 00000000..cc8532dc --- /dev/null +++ b/georiviere/river/templates/river/sql/pre_types.sql @@ -0,0 +1,9 @@ +DROP TYPE IF EXISTS elevation_infos; +CREATE TYPE elevation_infos AS ( + draped geometry, + slope float, + min_elevation integer, + max_elevation integer, + positive_gain integer, + negative_gain integer +); \ No newline at end of file From e80aabee234a585a6bddcda8198f58f23dd0c266 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Tue, 19 Dec 2023 10:45:08 +0100 Subject: [PATCH 05/26] use pg triggers --- georiviere/main/management/commands/migrate.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/georiviere/main/management/commands/migrate.py b/georiviere/main/management/commands/migrate.py index 0219458b..8d08a70f 100644 --- a/georiviere/main/management/commands/migrate.py +++ b/georiviere/main/management/commands/migrate.py @@ -20,16 +20,10 @@ def check_srid_has_meter_unit(): class Command(BaseCommand): def handle(self, *args, **options): check_srid_has_meter_unit() - # set_search_path() - # for app in apps.get_app_configs(): - # # move_models_to_schemas(app) - # load_sql_files(app, 'pre') + for app in apps.get_app_configs(): + load_sql_files(app, 'pre') super().handle(*args, **options) for app in apps.get_app_configs(): - # move_models_to_schemas(app) - try: - load_sql_files(app, 'post') - except Exception: - pass + load_sql_files(app, 'post') call_command('sync_translation_fields', '--noinput') call_command('update_translation_fields') From 29fb3b7f9f3fb198a243c07f50549481d5060579 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Tue, 19 Dec 2023 16:28:49 +0100 Subject: [PATCH 06/26] use pg triggers --- .../templates/river => main/templates/main}/sql/pre_types.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename georiviere/{river/templates/river => main/templates/main}/sql/pre_types.sql (100%) diff --git a/georiviere/river/templates/river/sql/pre_types.sql b/georiviere/main/templates/main/sql/pre_types.sql similarity index 100% rename from georiviere/river/templates/river/sql/pre_types.sql rename to georiviere/main/templates/main/sql/pre_types.sql From cafa103e18f0fdf48cb582f43265ae01d2bbc0ce Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Tue, 19 Dec 2023 16:44:48 +0100 Subject: [PATCH 07/26] use pg triggers --- .../{templates/main/sql/pre_types.sql => sql/pre_10_types.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename georiviere/main/{templates/main/sql/pre_types.sql => sql/pre_10_types.sql} (100%) diff --git a/georiviere/main/templates/main/sql/pre_types.sql b/georiviere/main/sql/pre_10_types.sql similarity index 100% rename from georiviere/main/templates/main/sql/pre_types.sql rename to georiviere/main/sql/pre_10_types.sql From 0e8dd4b42e18241ae6ec95287d0f8ad8b9b67e9f Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Tue, 19 Dec 2023 16:55:38 +0100 Subject: [PATCH 08/26] use pg triggers --- georiviere/main/management/commands/migrate.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/georiviere/main/management/commands/migrate.py b/georiviere/main/management/commands/migrate.py index 8d08a70f..8b607a0e 100644 --- a/georiviere/main/management/commands/migrate.py +++ b/georiviere/main/management/commands/migrate.py @@ -21,9 +21,12 @@ class Command(BaseCommand): def handle(self, *args, **options): check_srid_has_meter_unit() for app in apps.get_app_configs(): - load_sql_files(app, 'pre') + load_sql_files(app, 'pre') super().handle(*args, **options) for app in apps.get_app_configs(): - load_sql_files(app, 'post') + try: + load_sql_files(app, 'post') + except Exception: + pass call_command('sync_translation_fields', '--noinput') call_command('update_translation_fields') From c06dcc2fdf9ed531887ccb87d4c0d0bf11af1f9b Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Tue, 19 Dec 2023 17:37:57 +0100 Subject: [PATCH 09/26] use pg triggers --- georiviere/main/management/commands/migrate.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/georiviere/main/management/commands/migrate.py b/georiviere/main/management/commands/migrate.py index 8b607a0e..70fef977 100644 --- a/georiviere/main/management/commands/migrate.py +++ b/georiviere/main/management/commands/migrate.py @@ -22,11 +22,8 @@ def handle(self, *args, **options): check_srid_has_meter_unit() for app in apps.get_app_configs(): load_sql_files(app, 'pre') + load_sql_files(app, 'post') super().handle(*args, **options) - for app in apps.get_app_configs(): - try: - load_sql_files(app, 'post') - except Exception: - pass + call_command('sync_translation_fields', '--noinput') call_command('update_translation_fields') From 5f5628a08555bafe0953a95c8ba5cdd8f613cd10 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Tue, 19 Dec 2023 20:54:05 +0100 Subject: [PATCH 10/26] use pg triggers --- georiviere/main/sql/pre_10_types.sql | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 georiviere/main/sql/pre_10_types.sql diff --git a/georiviere/main/sql/pre_10_types.sql b/georiviere/main/sql/pre_10_types.sql deleted file mode 100644 index cc8532dc..00000000 --- a/georiviere/main/sql/pre_10_types.sql +++ /dev/null @@ -1,9 +0,0 @@ -DROP TYPE IF EXISTS elevation_infos; -CREATE TYPE elevation_infos AS ( - draped geometry, - slope float, - min_elevation integer, - max_elevation integer, - positive_gain integer, - negative_gain integer -); \ No newline at end of file From 555aaae6bcbc410701818152046ea4341fc82319 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Wed, 20 Dec 2023 12:47:53 +0100 Subject: [PATCH 11/26] use internal triggers --- docker-compose.yml | 1 - georiviere/altimetry.py | 21 ---- .../migrations/0025_auto_20231215_1124.py | 31 ------ .../migrations/0026_auto_20231218_1222.py | 47 --------- georiviere/description/models.py | 6 +- .../description/sql/post_10_triggers.sql | 7 ++ .../main/management/commands/migrate.py | 7 +- georiviere/main/sql/post_10_functions.sql | 16 +++ georiviere/main/sql/pre_10_cleanup.sql | 1 + .../migrations/0004_auto_20231215_1124.py | 19 ---- .../migrations/0005_auto_20231218_1222.py | 23 ----- georiviere/proceeding/models.py | 1 - .../river/management/commands/load_rivers.py | 2 +- .../migrations/0020_auto_20231215_1020.py | 19 ---- .../migrations/0021_auto_20231215_1051.py | 23 ----- .../migrations/0022_auto_20231215_1052.py | 23 ----- .../migrations/0023_auto_20231215_1056.py | 23 ----- .../migrations/0024_auto_20231218_1226.py | 27 ------ .../migrations/0025_auto_20231218_1325.py | 19 ---- .../migrations/0026_auto_20231218_1356.py | 23 ----- .../migrations/0027_auto_20231218_1400.py | 23 ----- .../migrations/0028_auto_20231218_1402.py | 23 ----- .../migrations/0029_auto_20231218_1403.py | 23 ----- .../migrations/0030_auto_20231218_1405.py | 23 ----- .../migrations/0031_auto_20231218_1405.py | 23 ----- .../migrations/0032_auto_20231218_1410.py | 19 ---- .../migrations/0033_auto_20231218_1412.py | 23 ----- .../migrations/0034_auto_20231218_1416.py | 23 ----- .../migrations/0035_auto_20231218_1418.py | 23 ----- .../migrations/0036_auto_20231218_1420.py | 23 ----- .../migrations/0037_auto_20231218_1421.py | 23 ----- .../migrations/0038_auto_20231218_1431.py | 23 ----- .../migrations/0039_auto_20231218_1601.py | 23 ----- .../migrations/0040_auto_20231218_1608.py | 23 ----- .../migrations/0041_auto_20231219_0932.py | 23 ----- georiviere/river/models.py | 97 +++++++++---------- georiviere/river/sql/post_10_triggers.sql | 43 ++++++++ georiviere/river/sql/pre_10_cleanup.sql | 3 + georiviere/settings/__init__.py | 2 +- requirements.in | 1 - requirements.txt | 3 - 41 files changed, 127 insertions(+), 702 deletions(-) delete mode 100644 georiviere/description/migrations/0025_auto_20231215_1124.py delete mode 100644 georiviere/description/migrations/0026_auto_20231218_1222.py create mode 100644 georiviere/description/sql/post_10_triggers.sql create mode 100644 georiviere/main/sql/post_10_functions.sql create mode 100644 georiviere/main/sql/pre_10_cleanup.sql delete mode 100644 georiviere/proceeding/migrations/0004_auto_20231215_1124.py delete mode 100644 georiviere/proceeding/migrations/0005_auto_20231218_1222.py delete mode 100644 georiviere/river/migrations/0020_auto_20231215_1020.py delete mode 100644 georiviere/river/migrations/0021_auto_20231215_1051.py delete mode 100644 georiviere/river/migrations/0022_auto_20231215_1052.py delete mode 100644 georiviere/river/migrations/0023_auto_20231215_1056.py delete mode 100644 georiviere/river/migrations/0024_auto_20231218_1226.py delete mode 100644 georiviere/river/migrations/0025_auto_20231218_1325.py delete mode 100644 georiviere/river/migrations/0026_auto_20231218_1356.py delete mode 100644 georiviere/river/migrations/0027_auto_20231218_1400.py delete mode 100644 georiviere/river/migrations/0028_auto_20231218_1402.py delete mode 100644 georiviere/river/migrations/0029_auto_20231218_1403.py delete mode 100644 georiviere/river/migrations/0030_auto_20231218_1405.py delete mode 100644 georiviere/river/migrations/0031_auto_20231218_1405.py delete mode 100644 georiviere/river/migrations/0032_auto_20231218_1410.py delete mode 100644 georiviere/river/migrations/0033_auto_20231218_1412.py delete mode 100644 georiviere/river/migrations/0034_auto_20231218_1416.py delete mode 100644 georiviere/river/migrations/0035_auto_20231218_1418.py delete mode 100644 georiviere/river/migrations/0036_auto_20231218_1420.py delete mode 100644 georiviere/river/migrations/0037_auto_20231218_1421.py delete mode 100644 georiviere/river/migrations/0038_auto_20231218_1431.py delete mode 100644 georiviere/river/migrations/0039_auto_20231218_1601.py delete mode 100644 georiviere/river/migrations/0040_auto_20231218_1608.py delete mode 100644 georiviere/river/migrations/0041_auto_20231219_0932.py create mode 100644 georiviere/river/sql/post_10_triggers.sql create mode 100644 georiviere/river/sql/pre_10_cleanup.sql diff --git a/docker-compose.yml b/docker-compose.yml index 64b778d6..f519fdc4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -20,7 +20,6 @@ services: web: image: georiviere:latest - user: $UID:$GID build: context: . target: dev diff --git a/georiviere/altimetry.py b/georiviere/altimetry.py index e9b7335f..d36c1c74 100644 --- a/georiviere/altimetry.py +++ b/georiviere/altimetry.py @@ -1,27 +1,6 @@ -import pgtrigger from geotrek.altimetry.models import AltimetryMixin as BaseAltimetryMixin class AltimetryMixin(BaseAltimetryMixin): class Meta: abstract = True - triggers = [ - pgtrigger.Trigger( - name="keep_in_sync", - operation=pgtrigger.UpdateOf('geom') | pgtrigger.Insert, - when=pgtrigger.Before, - declare=[('elevation', 'elevation_infos')], - func=""" - SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation; - -- Update path geometry - NEW.geom_3d := elevation.draped; - NEW.length := ST_3DLength(elevation.draped); - NEW.slope := elevation.slope; - NEW.min_elevation := elevation.min_elevation; - NEW.max_elevation := elevation.max_elevation; - NEW.ascent := elevation.positive_gain; - NEW.descent := elevation.negative_gain; - RETURN NEW; - """ - ) - ] diff --git a/georiviere/description/migrations/0025_auto_20231215_1124.py b/georiviere/description/migrations/0025_auto_20231215_1124.py deleted file mode 100644 index 957a97dd..00000000 --- a/georiviere/description/migrations/0025_auto_20231215_1124.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-15 11:24 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('description', '0024_auto_20230323_1621'), - ] - - operations = [ - pgtrigger.migrations.AddTrigger( - model_name='land', - trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n\n RETURN NEW;\n ', hash='82ffa7255d1e65c383b05ef0fa226da73a7ad6c8', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_fb8bb', table='description_land', when='BEFORE')), - ), - pgtrigger.migrations.AddTrigger( - model_name='morphology', - trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n\n RETURN NEW;\n ', hash='f2e3c5183c820b762d1336a39135727ffc39c5e3', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_472ec', table='description_morphology', when='BEFORE')), - ), - pgtrigger.migrations.AddTrigger( - model_name='status', - trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n\n RETURN NEW;\n ', hash='9ebcbb87cf2196d3c04e0e624571d3a49b1ebb69', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_aa87c', table='description_status', when='BEFORE')), - ), - pgtrigger.migrations.AddTrigger( - model_name='usage', - trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n\n RETURN NEW;\n ', hash='c18fa3553e1c897d5a5e5f3b6cc5836c86429190', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_71b71', table='description_usage', when='BEFORE')), - ), - ] diff --git a/georiviere/description/migrations/0026_auto_20231218_1222.py b/georiviere/description/migrations/0026_auto_20231218_1222.py deleted file mode 100644 index b16732c9..00000000 --- a/georiviere/description/migrations/0026_auto_20231218_1222.py +++ /dev/null @@ -1,47 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 12:22 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('description', '0025_auto_20231215_1124'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='land', - name='keep_in_sync', - ), - pgtrigger.migrations.RemoveTrigger( - model_name='morphology', - name='keep_in_sync', - ), - pgtrigger.migrations.RemoveTrigger( - model_name='status', - name='keep_in_sync', - ), - pgtrigger.migrations.RemoveTrigger( - model_name='usage', - name='keep_in_sync', - ), - pgtrigger.migrations.AddTrigger( - model_name='land', - trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n RETURN NEW;\n ', hash='d639f6850243942a05ed1f44f6cf79b88b563bad', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_fb8bb', table='description_land', when='BEFORE')), - ), - pgtrigger.migrations.AddTrigger( - model_name='morphology', - trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n RETURN NEW;\n ', hash='048fe3697643f7682b5336def02a2a9d345947ae', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_472ec', table='description_morphology', when='BEFORE')), - ), - pgtrigger.migrations.AddTrigger( - model_name='status', - trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n RETURN NEW;\n ', hash='967fa66b6c8eb5e17d5bfc49594c2573241d073b', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_aa87c', table='description_status', when='BEFORE')), - ), - pgtrigger.migrations.AddTrigger( - model_name='usage', - trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n RETURN NEW;\n ', hash='69cb0cd06f0dccdca1f09d54169f5a673b87fca5', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_71b71', table='description_usage', when='BEFORE')), - ), - ] diff --git a/georiviere/description/models.py b/georiviere/description/models.py index cd686bb5..5be80af1 100644 --- a/georiviere/description/models.py +++ b/georiviere/description/models.py @@ -199,7 +199,7 @@ class Morphology(AddPropertyBufferMixin, TopologyMixin, TimeStampedModelMixin, class Meta: verbose_name = _("Morphology") verbose_name_plural = _("Morphologies") - triggers = AltimetryMixin.Meta.triggers + # triggers = AltimetryMixin.Meta.triggers def __str__(self): if self.main_flow: @@ -269,7 +269,6 @@ class Land(AddPropertyBufferMixin, TimeStampedModelMixin, WatershedPropertiesMix class Meta: verbose_name = _("Land") verbose_name_plural = _("Lands") - triggers = AltimetryMixin.Meta.triggers def __str__(self): return f"{self.land_type}" @@ -308,7 +307,6 @@ class Usage(AddPropertyBufferMixin, TimeStampedModelMixin, WatershedPropertiesMi class Meta: verbose_name = _("Usage") verbose_name_plural = _("Usages") - triggers = AltimetryMixin.Meta.triggers def __str__(self): return ', '.join(self.usage_types.values_list("label", flat=True)) @@ -357,7 +355,7 @@ class Status(TopologyMixin, AddPropertyBufferMixin, TimeStampedModelMixin, Water class Meta: verbose_name = _("Status") verbose_name_plural = _("Statuses") - triggers = AltimetryMixin.Meta.triggers + # triggers = AltimetryMixin.Meta.triggers def __str__(self): if self.status_types.count(): diff --git a/georiviere/description/sql/post_10_triggers.sql b/georiviere/description/sql/post_10_triggers.sql new file mode 100644 index 00000000..e801d311 --- /dev/null +++ b/georiviere/description/sql/post_10_triggers.sql @@ -0,0 +1,7 @@ +CREATE TRIGGER description_morphology_10_elevation +BEFORE INSERT OR UPDATE OF geom ON description_morphology +FOR EACH ROW EXECUTE PROCEDURE elevation(); + +CREATE TRIGGER description_status_10_elevation +BEFORE INSERT OR UPDATE OF geom ON description_status +FOR EACH ROW EXECUTE PROCEDURE elevation(); \ No newline at end of file diff --git a/georiviere/main/management/commands/migrate.py b/georiviere/main/management/commands/migrate.py index 70fef977..8b607a0e 100644 --- a/georiviere/main/management/commands/migrate.py +++ b/georiviere/main/management/commands/migrate.py @@ -22,8 +22,11 @@ def handle(self, *args, **options): check_srid_has_meter_unit() for app in apps.get_app_configs(): load_sql_files(app, 'pre') - load_sql_files(app, 'post') super().handle(*args, **options) - + for app in apps.get_app_configs(): + try: + load_sql_files(app, 'post') + except Exception: + pass call_command('sync_translation_fields', '--noinput') call_command('update_translation_fields') diff --git a/georiviere/main/sql/post_10_functions.sql b/georiviere/main/sql/post_10_functions.sql new file mode 100644 index 00000000..c11aba35 --- /dev/null +++ b/georiviere/main/sql/post_10_functions.sql @@ -0,0 +1,16 @@ +CREATE FUNCTION elevation() RETURNS trigger SECURITY DEFINER AS $$ +DECLARE + elevation elevation_infos; +BEGIN + SELECT * FROM ft_elevation_infos(NEW.geom, {{ ALTIMETRIC_PROFILE_STEP }}) INTO elevation; + -- Update path geometry + NEW.geom_3d := elevation.draped; + NEW.length := ST_3DLength(elevation.draped); + NEW.slope := elevation.slope; + NEW.min_elevation := elevation.min_elevation; + NEW.max_elevation := elevation.max_elevation; + NEW.ascent := elevation.positive_gain; + NEW.descent := elevation.negative_gain; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; diff --git a/georiviere/main/sql/pre_10_cleanup.sql b/georiviere/main/sql/pre_10_cleanup.sql new file mode 100644 index 00000000..1c034839 --- /dev/null +++ b/georiviere/main/sql/pre_10_cleanup.sql @@ -0,0 +1 @@ +DROP FUNCTION IF EXISTS elevation() CASCADE; \ No newline at end of file diff --git a/georiviere/proceeding/migrations/0004_auto_20231215_1124.py b/georiviere/proceeding/migrations/0004_auto_20231215_1124.py deleted file mode 100644 index 01a23413..00000000 --- a/georiviere/proceeding/migrations/0004_auto_20231215_1124.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-15 11:24 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('proceeding', '0003_auto_20210804_1014'), - ] - - operations = [ - pgtrigger.migrations.AddTrigger( - model_name='proceeding', - trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n\n RETURN NEW;\n ', hash='4580ed3c25a4cd5a156ff3a0c1efd6c8301d8e25', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_6ba14', table='proceeding_proceeding', when='BEFORE')), - ), - ] diff --git a/georiviere/proceeding/migrations/0005_auto_20231218_1222.py b/georiviere/proceeding/migrations/0005_auto_20231218_1222.py deleted file mode 100644 index 5a7e4ac6..00000000 --- a/georiviere/proceeding/migrations/0005_auto_20231218_1222.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 12:22 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('proceeding', '0004_auto_20231215_1124'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='proceeding', - name='keep_in_sync', - ), - pgtrigger.migrations.AddTrigger( - model_name='proceeding', - trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n RETURN NEW;\n ', hash='8be1e3d34cf0ef421d9f1750b10e7ef296d6a20d', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_6ba14', table='proceeding_proceeding', when='BEFORE')), - ), - ] diff --git a/georiviere/proceeding/models.py b/georiviere/proceeding/models.py index c88520b7..ab6627a3 100644 --- a/georiviere/proceeding/models.py +++ b/georiviere/proceeding/models.py @@ -49,7 +49,6 @@ def get_create_label(cls): class Meta: verbose_name = _("Proceeding") verbose_name_plural = _("Proceedings") - triggers = AltimetryMixin.Meta.triggers class Event(models.Model): diff --git a/georiviere/river/management/commands/load_rivers.py b/georiviere/river/management/commands/load_rivers.py index eca252d8..07b1acca 100644 --- a/georiviere/river/management/commands/load_rivers.py +++ b/georiviere/river/management/commands/load_rivers.py @@ -34,7 +34,7 @@ def handle(self, *args, **options): Stream.objects.all().delete() self.stdout.write(self.style.SUCCESS("done!")) - batch_size = 100 + batch_size = 50 objs = (Stream(geom=feat.geom.geos, source_location=Point(feat.geom.geos[0]), diff --git a/georiviere/river/migrations/0020_auto_20231215_1020.py b/georiviere/river/migrations/0020_auto_20231215_1020.py deleted file mode 100644 index e5421117..00000000 --- a/georiviere/river/migrations/0020_auto_20231215_1020.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-15 10:20 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0019_stream_description'), - ] - - operations = [ - pgtrigger.migrations.AddTrigger( - model_name='stream', - trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation JSONB;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n RETURN NEW;\n ', hash='6c62fd64699ff351273ae8753db0b43dd5defaf7', operation='UPDATE OR INSERT', pgid='pgtrigger_keep_in_sync_7a86b', table='river_stream', when='BEFORE')), - ), - ] diff --git a/georiviere/river/migrations/0021_auto_20231215_1051.py b/georiviere/river/migrations/0021_auto_20231215_1051.py deleted file mode 100644 index bd951d1f..00000000 --- a/georiviere/river/migrations/0021_auto_20231215_1051.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-15 10:51 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0020_auto_20231215_1020'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='stream', - name='keep_in_sync', - ), - pgtrigger.migrations.AddTrigger( - model_name='stream', - trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := element.draped;\n NEW.length := ST_3DLength(element.draped);\n NEW.slope := element.slope;\n NEW.min_elevation := element.min_elevation;\n NEW.max_elevation := element.max_elevation;\n NEW.ascent := element.positive_gain;\n NEW.descent := element.negative_gain;\n\n RETURN NEW;\n ', hash='fdeef3b3432dda345b1ec896b91e84eb120a9986', operation='UPDATE OR INSERT', pgid='pgtrigger_keep_in_sync_7a86b', table='river_stream', when='BEFORE')), - ), - ] diff --git a/georiviere/river/migrations/0022_auto_20231215_1052.py b/georiviere/river/migrations/0022_auto_20231215_1052.py deleted file mode 100644 index 9a4e0b26..00000000 --- a/georiviere/river/migrations/0022_auto_20231215_1052.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-15 10:52 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0021_auto_20231215_1051'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='stream', - name='keep_in_sync', - ), - pgtrigger.migrations.AddTrigger( - model_name='stream', - trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n\n RETURN NEW;\n ', hash='24de00d1e6f9be9e088db3410e54b0de328653a3', operation='UPDATE OR INSERT', pgid='pgtrigger_keep_in_sync_7a86b', table='river_stream', when='BEFORE')), - ), - ] diff --git a/georiviere/river/migrations/0023_auto_20231215_1056.py b/georiviere/river/migrations/0023_auto_20231215_1056.py deleted file mode 100644 index 6e669b8a..00000000 --- a/georiviere/river/migrations/0023_auto_20231215_1056.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-15 10:56 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0022_auto_20231215_1052'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='stream', - name='keep_in_sync', - ), - pgtrigger.migrations.AddTrigger( - model_name='stream', - trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n\n RETURN NEW;\n ', hash='168b84532fa3b4230f53fbd1cfdb1169c5d72a0a', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_7a86b', table='river_stream', when='BEFORE')), - ), - ] diff --git a/georiviere/river/migrations/0024_auto_20231218_1226.py b/georiviere/river/migrations/0024_auto_20231218_1226.py deleted file mode 100644 index 4d4f21a1..00000000 --- a/georiviere/river/migrations/0024_auto_20231218_1226.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 12:26 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0023_auto_20231215_1056'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='stream', - name='keep_in_sync', - ), - pgtrigger.migrations.AddTrigger( - model_name='stream', - trigger=pgtrigger.compiler.Trigger(name='keep_in_sync', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos;', func='\n SELECT * FROM ft_elevation_infos(NEW.geom, 20) INTO elevation;\n -- Update path geometry\n NEW.geom_3d := elevation.draped;\n NEW.length := ST_3DLength(elevation.draped);\n NEW.slope := elevation.slope;\n NEW.min_elevation := elevation.min_elevation;\n NEW.max_elevation := elevation.max_elevation;\n NEW.ascent := elevation.positive_gain;\n NEW.descent := elevation.negative_gain;\n RETURN NEW;\n ', hash='e66f827b3e0e2d3e5f822a259752f2d8a48a7c26', operation='UPDATE OF "geom" OR INSERT', pgid='pgtrigger_keep_in_sync_7a86b', table='river_stream', when='BEFORE')), - ), - pgtrigger.migrations.AddTrigger( - model_name='topology', - trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos; geom geometry;', func='\n IF (NEW.start_point != OLD.start_point OR NEW.end_point != OLD.end_point) THEN \n SELECT geom FROM river_stream r WHERE NEW.id = r.id INTO geom;\n UPDATE description_morphology\n SET geom = ST_LINESUBSTRING(geom, NEW.START_POINT, NEW.END_POINT)\n WHERE topology_id = NEW.id; \n UPDATE description_status\n SET geom = ST_LINESUBSTRING(geom, NEW.START_POINT, NEW.END_POINT)\n WHERE topology_id = NEW.id; \n END IF;\n RETURN NEW;\n ', hash='db1df9343d9079232a59df61b34bfcd7bc2df48a', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='BEFORE')), - ), - ] diff --git a/georiviere/river/migrations/0025_auto_20231218_1325.py b/georiviere/river/migrations/0025_auto_20231218_1325.py deleted file mode 100644 index 74c03ca5..00000000 --- a/georiviere/river/migrations/0025_auto_20231218_1325.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 13:25 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0024_auto_20231218_1226'), - ] - - operations = [ - pgtrigger.migrations.AddTrigger( - model_name='stream', - trigger=pgtrigger.compiler.Trigger(name='create_topologies', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE topology_morphology integer; topology_status integer;', func='\n INSERT INTO river_topology (stream_id, start_position, end_position)\n VALUES (NEW.id, 0, 1) RETURNING id INTO topology_morphology;\n INSERT INTO description_morphology (topology_id, geom) VALUES (topology_morphology, NEW.geom);\n INSERT INTO river_topology (stream_id, start_position, end_position)\n VALUES (NEW.id, 0, 1) RETURNING id INTO topology_status;\n INSERT INTO description_status (topology_id, geom) VALUES (topology_status, NEW.geom);\n RETURN NEW;\n ', hash='c0b7e1615c64b92e36e49803f3001ebde7dd517e', operation='INSERT', pgid='pgtrigger_create_topologies_e8d7d', table='river_stream', when='AFTER')), - ), - ] diff --git a/georiviere/river/migrations/0026_auto_20231218_1356.py b/georiviere/river/migrations/0026_auto_20231218_1356.py deleted file mode 100644 index 45b90ad4..00000000 --- a/georiviere/river/migrations/0026_auto_20231218_1356.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 13:56 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0025_auto_20231218_1325'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='topology', - name='update_topology_geom', - ), - pgtrigger.migrations.AddTrigger( - model_name='topology', - trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos; geom geometry;', func='\n IF (NEW.start_position != OLD.start_position OR NEW.end_position != OLD.end_position) THEN \n SELECT geom FROM river_stream r WHERE NEW.id = r.id INTO geom;\n UPDATE description_morphology\n SET geom = ST_LINESUBSTRING(geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n UPDATE description_status\n SET geom = ST_LINESUBSTRING(geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n END IF;\n RETURN NEW;\n ', hash='10d2e4894631bee97f91deeb607004d3a5295448', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='BEFORE')), - ), - ] diff --git a/georiviere/river/migrations/0027_auto_20231218_1400.py b/georiviere/river/migrations/0027_auto_20231218_1400.py deleted file mode 100644 index f32c8f08..00000000 --- a/georiviere/river/migrations/0027_auto_20231218_1400.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 14:00 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0026_auto_20231218_1356'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='stream', - name='create_topologies', - ), - pgtrigger.migrations.AddTrigger( - model_name='stream', - trigger=pgtrigger.compiler.Trigger(name='create_topologies', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE topology_morphology integer; topology_status integer;', func='\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_morphology;\n INSERT INTO description_morphology (topology_id, geom) VALUES (topology_morphology, NEW.geom);\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_status;\n INSERT INTO description_status (topology_id, geom) VALUES (topology_status, NEW.geom);\n RETURN NEW;\n ', hash='4ebe61234dd666bf424de96761a8af7e0a72560f', operation='INSERT', pgid='pgtrigger_create_topologies_e8d7d', table='river_stream', when='AFTER')), - ), - ] diff --git a/georiviere/river/migrations/0028_auto_20231218_1402.py b/georiviere/river/migrations/0028_auto_20231218_1402.py deleted file mode 100644 index 227b45d4..00000000 --- a/georiviere/river/migrations/0028_auto_20231218_1402.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 14:02 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0027_auto_20231218_1400'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='stream', - name='create_topologies', - ), - pgtrigger.migrations.AddTrigger( - model_name='stream', - trigger=pgtrigger.compiler.Trigger(name='create_topologies', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE topology_morphology integer; topology_status integer;', func='\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_morphology;\n INSERT INTO description_morphology (topology_id, geom, date_insert, date_update) VALUES (topology_morphology, NEW.geom, NOW(), NOW());\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_status;\n INSERT INTO description_status (topology_id, geom, date_insert, date_update) VALUES (topology_status, NEW.geom, NOW(), NOW());\n RETURN NEW;\n ', hash='606f9274946baa820c7792e04a1f6559948a2e8e', operation='INSERT', pgid='pgtrigger_create_topologies_e8d7d', table='river_stream', when='AFTER')), - ), - ] diff --git a/georiviere/river/migrations/0029_auto_20231218_1403.py b/georiviere/river/migrations/0029_auto_20231218_1403.py deleted file mode 100644 index 8416c313..00000000 --- a/georiviere/river/migrations/0029_auto_20231218_1403.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 14:03 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0028_auto_20231218_1402'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='stream', - name='create_topologies', - ), - pgtrigger.migrations.AddTrigger( - model_name='stream', - trigger=pgtrigger.compiler.Trigger(name='create_topologies', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE topology_morphology integer; topology_status integer;', func="\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_morphology;\n INSERT INTO description_morphology (topology_id, geom, description, date_insert, date_update)\n VALUES (topology_morphology, NEW.geom, '', NOW(), NOW());\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_status;\n INSERT INTO description_status (topology_id, geom, date_insert, date_update) VALUES (topology_status, NEW.geom, NOW(), NOW());\n RETURN NEW;\n ", hash='cfb353801531d9e2c134a09c85d8a69807704a71', operation='INSERT', pgid='pgtrigger_create_topologies_e8d7d', table='river_stream', when='AFTER')), - ), - ] diff --git a/georiviere/river/migrations/0030_auto_20231218_1405.py b/georiviere/river/migrations/0030_auto_20231218_1405.py deleted file mode 100644 index 1ef79185..00000000 --- a/georiviere/river/migrations/0030_auto_20231218_1405.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 14:05 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0029_auto_20231218_1403'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='stream', - name='create_topologies', - ), - pgtrigger.migrations.AddTrigger( - model_name='stream', - trigger=pgtrigger.compiler.Trigger(name='create_topologies', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE topology_morphology integer; topology_status integer;', func="\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_morphology;\n INSERT INTO description_morphology (topology_id, geom, description, date_insert, date_update)\n VALUES (topology_morphology, NEW.geom, '', NOW(), NOW());\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_status;\n INSERT INTO description_status (topology_id, geom, regulation, referencial, descrption, date_insert, date_update)\n VALUES (topology_status, NEW.geom, FALSE, FALSE, '', NOW(), NOW());\n RETURN NEW;\n ", hash='f5c7079e6d4e21c67d642ea14d61d4e2f39787b0', operation='INSERT', pgid='pgtrigger_create_topologies_e8d7d', table='river_stream', when='AFTER')), - ), - ] diff --git a/georiviere/river/migrations/0031_auto_20231218_1405.py b/georiviere/river/migrations/0031_auto_20231218_1405.py deleted file mode 100644 index 2dbd1031..00000000 --- a/georiviere/river/migrations/0031_auto_20231218_1405.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 14:05 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0030_auto_20231218_1405'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='stream', - name='create_topologies', - ), - pgtrigger.migrations.AddTrigger( - model_name='stream', - trigger=pgtrigger.compiler.Trigger(name='create_topologies', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE topology_morphology integer; topology_status integer;', func="\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_morphology;\n INSERT INTO description_morphology (topology_id, geom, description, date_insert, date_update)\n VALUES (topology_morphology, NEW.geom, '', NOW(), NOW());\n INSERT INTO river_topology (stream_id, start_position, end_position, qualified)\n VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_status;\n INSERT INTO description_status (topology_id, geom, regulation, referencial, description, date_insert, date_update)\n VALUES (topology_status, NEW.geom, FALSE, FALSE, '', NOW(), NOW());\n RETURN NEW;\n ", hash='e846f76834647fd2338681a9530765b6d1883cc9', operation='INSERT', pgid='pgtrigger_create_topologies_e8d7d', table='river_stream', when='AFTER')), - ), - ] diff --git a/georiviere/river/migrations/0032_auto_20231218_1410.py b/georiviere/river/migrations/0032_auto_20231218_1410.py deleted file mode 100644 index 1e19b353..00000000 --- a/georiviere/river/migrations/0032_auto_20231218_1410.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 14:10 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0031_auto_20231218_1405'), - ] - - operations = [ - pgtrigger.migrations.AddTrigger( - model_name='stream', - trigger=pgtrigger.compiler.Trigger(name='update_topologies', sql=pgtrigger.compiler.UpsertTriggerSql(func='\n UPDATE river_topology SET start_position=start_position WHERE stream_id=NEW.id;\n RETURN NEW;\n ', hash='0b6322b6b455eed7b6a2a78c79b07e08e9a86611', operation='UPDATE OF "geom"', pgid='pgtrigger_update_topologies_6ab45', table='river_stream', when='AFTER')), - ), - ] diff --git a/georiviere/river/migrations/0033_auto_20231218_1412.py b/georiviere/river/migrations/0033_auto_20231218_1412.py deleted file mode 100644 index 1b5d52e2..00000000 --- a/georiviere/river/migrations/0033_auto_20231218_1412.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 14:12 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0032_auto_20231218_1410'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='topology', - name='update_topology_geom', - ), - pgtrigger.migrations.AddTrigger( - model_name='topology', - trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos; geom geometry;', func='\n SELECT geom FROM river_stream r WHERE NEW.id = r.id INTO geom;\n UPDATE description_morphology\n SET geom = ST_LINESUBSTRING(geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n UPDATE description_status\n SET geom = ST_LINESUBSTRING(geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n RETURN NEW;\n ', hash='2b83b20dab6aa7e5456c1e10694f527dc98eb281', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='BEFORE')), - ), - ] diff --git a/georiviere/river/migrations/0034_auto_20231218_1416.py b/georiviere/river/migrations/0034_auto_20231218_1416.py deleted file mode 100644 index 653b8de5..00000000 --- a/georiviere/river/migrations/0034_auto_20231218_1416.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 14:16 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0033_auto_20231218_1412'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='topology', - name='update_topology_geom', - ), - pgtrigger.migrations.AddTrigger( - model_name='topology', - trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos; geom geometry;', func='\n SELECT r.geom FROM river_stream r WHERE NEW.id = r.id INTO geom;\n UPDATE description_morphology\n SET geom = ST_LINESUBSTRING(geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n UPDATE description_status\n SET geom = ST_LINESUBSTRING(geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n RETURN NEW;\n ', hash='1e3e1dbd526ffd01e8155aec62fad614e188471d', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='BEFORE')), - ), - ] diff --git a/georiviere/river/migrations/0035_auto_20231218_1418.py b/georiviere/river/migrations/0035_auto_20231218_1418.py deleted file mode 100644 index e92cd864..00000000 --- a/georiviere/river/migrations/0035_auto_20231218_1418.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 14:18 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0034_auto_20231218_1416'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='topology', - name='update_topology_geom', - ), - pgtrigger.migrations.AddTrigger( - model_name='topology', - trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos; geom geometry;', func='\n SELECT r.geom FROM river_stream r WHERE NEW.id = r.id INTO geom;\n UPDATE description_morphology m\n SET m.geom = ST_LINESUBSTRING(geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n UPDATE description_status s\n SET s.geom = ST_LINESUBSTRING(geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n RETURN NEW;\n ', hash='a3d43086e66e04cde5bf979df1f4565a3bb9e791', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='BEFORE')), - ), - ] diff --git a/georiviere/river/migrations/0036_auto_20231218_1420.py b/georiviere/river/migrations/0036_auto_20231218_1420.py deleted file mode 100644 index 4421a74f..00000000 --- a/georiviere/river/migrations/0036_auto_20231218_1420.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 14:20 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0035_auto_20231218_1418'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='topology', - name='update_topology_geom', - ), - pgtrigger.migrations.AddTrigger( - model_name='topology', - trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos; stream_geom geometry;', func='\n SELECT r.geom FROM river_stream r WHERE NEW.id = r.id INTO stream_geom;\n UPDATE description_morphology m\n SET m.geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n UPDATE description_status s\n SET s.geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n RETURN NEW;\n ', hash='1671ae29035c32a992993d3518965e8e9c0a605f', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='BEFORE')), - ), - ] diff --git a/georiviere/river/migrations/0037_auto_20231218_1421.py b/georiviere/river/migrations/0037_auto_20231218_1421.py deleted file mode 100644 index 1739897b..00000000 --- a/georiviere/river/migrations/0037_auto_20231218_1421.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 14:21 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0036_auto_20231218_1420'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='topology', - name='update_topology_geom', - ), - pgtrigger.migrations.AddTrigger( - model_name='topology', - trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE elevation elevation_infos; stream_geom geometry;', func='\n SELECT r.geom FROM river_stream r WHERE NEW.id = r.id INTO stream_geom;\n UPDATE description_morphology\n SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n UPDATE description_status\n SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n RETURN NEW;\n ', hash='444948eb36585ca5ea4dfdad5e9be32137e67844', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='BEFORE')), - ), - ] diff --git a/georiviere/river/migrations/0038_auto_20231218_1431.py b/georiviere/river/migrations/0038_auto_20231218_1431.py deleted file mode 100644 index 26019979..00000000 --- a/georiviere/river/migrations/0038_auto_20231218_1431.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 14:31 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0037_auto_20231218_1421'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='topology', - name='update_topology_geom', - ), - pgtrigger.migrations.AddTrigger( - model_name='topology', - trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE stream_geom geometry;', func='\n SELECT r.geom FROM river_stream r WHERE NEW.id = r.id INTO stream_geom;\n UPDATE description_morphology\n SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n UPDATE description_status\n SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n RETURN NEW;\n ', hash='f0a3386a26d41f8268db5bbdb554ba4cc3ae1612', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='AFTER')), - ), - ] diff --git a/georiviere/river/migrations/0039_auto_20231218_1601.py b/georiviere/river/migrations/0039_auto_20231218_1601.py deleted file mode 100644 index 06a328cb..00000000 --- a/georiviere/river/migrations/0039_auto_20231218_1601.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 16:01 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0038_auto_20231218_1431'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='stream', - name='update_topologies', - ), - pgtrigger.migrations.AddTrigger( - model_name='stream', - trigger=pgtrigger.compiler.Trigger(name='update_topologies', sql=pgtrigger.compiler.UpsertTriggerSql(func='\n UPDATE river_topology SET id=id WHERE stream_id=NEW.id;\n RETURN NEW;\n ', hash='704192b93012d12fa95b06b03618981a49609a4e', operation='UPDATE OF "geom"', pgid='pgtrigger_update_topologies_6ab45', table='river_stream', when='AFTER')), - ), - ] diff --git a/georiviere/river/migrations/0040_auto_20231218_1608.py b/georiviere/river/migrations/0040_auto_20231218_1608.py deleted file mode 100644 index ad4c8f4d..00000000 --- a/georiviere/river/migrations/0040_auto_20231218_1608.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-18 16:08 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0039_auto_20231218_1601'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='topology', - name='update_topology_geom', - ), - pgtrigger.migrations.AddTrigger( - model_name='topology', - trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE stream_geom geometry;', func='\n SELECT r.geom FROM river_stream r WHERE NEW.stream_id = r.id INTO stream_geom;\n UPDATE description_morphology\n SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n UPDATE description_status\n SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id; \n RETURN NEW;\n ', hash='4d63b6e0ef200235882742af37d834d00b5a271a', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='AFTER')), - ), - ] diff --git a/georiviere/river/migrations/0041_auto_20231219_0932.py b/georiviere/river/migrations/0041_auto_20231219_0932.py deleted file mode 100644 index 12429cd4..00000000 --- a/georiviere/river/migrations/0041_auto_20231219_0932.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2023-12-19 09:32 - -from django.db import migrations -import pgtrigger.compiler -import pgtrigger.migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('river', '0040_auto_20231218_1608'), - ] - - operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name='topology', - name='update_topology_geom', - ), - pgtrigger.migrations.AddTrigger( - model_name='topology', - trigger=pgtrigger.compiler.Trigger(name='update_topology_geom', sql=pgtrigger.compiler.UpsertTriggerSql(declare='DECLARE stream_geom geometry;', func='\n SELECT r.geom FROM river_stream r WHERE NEW.stream_id = r.id INTO stream_geom;\n UPDATE description_morphology\n SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id;\n UPDATE description_status\n SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position)\n WHERE topology_id = NEW.id;\n RETURN NEW;\n ', hash='0d8dce1088e59bd290e9ffe0d6bfb8a2493a5c1c', operation='UPDATE OR INSERT', pgid='pgtrigger_update_topology_geom_011ed', table='river_topology', when='AFTER')), - ), - ] diff --git a/georiviere/river/models.py b/georiviere/river/models.py index 9283a84c..041cab52 100644 --- a/georiviere/river/models.py +++ b/georiviere/river/models.py @@ -1,4 +1,3 @@ -import pgtrigger from django.conf import settings from django.contrib.contenttypes.models import ContentType from django.contrib.gis.db import models @@ -97,37 +96,37 @@ class FlowChoices(models.IntegerChoices): class Meta: verbose_name = _("Stream") verbose_name_plural = _("Streams") - triggers = AltimetryMixin.Meta.triggers + [ - pgtrigger.Trigger( - name="create_topologies", - operation=pgtrigger.Insert, - declare=[ - ('topology_morphology', 'integer'), - ('topology_status', 'integer') - ], - when=pgtrigger.After, - func=""" - INSERT INTO river_topology (stream_id, start_position, end_position, qualified) - VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_morphology; - INSERT INTO description_morphology (topology_id, geom, description, date_insert, date_update) - VALUES (topology_morphology, NEW.geom, '', NOW(), NOW()); - INSERT INTO river_topology (stream_id, start_position, end_position, qualified) - VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_status; - INSERT INTO description_status (topology_id, geom, regulation, referencial, description, date_insert, date_update) - VALUES (topology_status, NEW.geom, FALSE, FALSE, '', NOW(), NOW()); - RETURN NEW; - """ - ), - pgtrigger.Trigger( - name="update_topologies", - operation=pgtrigger.UpdateOf('geom'), - when=pgtrigger.After, - func=""" - UPDATE river_topology SET id=id WHERE stream_id=NEW.id; - RETURN NEW; - """ - ) - ] + # triggers = AltimetryMixin.Meta.triggers + [ + # pgtrigger.Trigger( + # name="create_topologies", + # operation=pgtrigger.Insert, + # declare=[ + # ('topology_morphology', 'integer'), + # ('topology_status', 'integer') + # ], + # when=pgtrigger.After, + # func=""" + # INSERT INTO river_topology (stream_id, start_position, end_position, qualified) + # VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_morphology; + # INSERT INTO description_morphology (topology_id, geom, description, date_insert, date_update) + # VALUES (topology_morphology, NEW.geom, '', NOW(), NOW()); + # INSERT INTO river_topology (stream_id, start_position, end_position, qualified) + # VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_status; + # INSERT INTO description_status (topology_id, geom, regulation, referencial, description, date_insert, date_update) + # VALUES (topology_status, NEW.geom, FALSE, FALSE, '', NOW(), NOW()); + # RETURN NEW; + # """ + # ), + # pgtrigger.Trigger( + # name="update_topologies", + # operation=pgtrigger.UpdateOf('geom'), + # when=pgtrigger.After, + # func=""" + # UPDATE river_topology SET id=id WHERE stream_id=NEW.id; + # RETURN NEW; + # """ + # ) + # ] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -251,23 +250,23 @@ def __str__(self): class Meta: verbose_name = _("Topology") verbose_name_plural = _("Topologies") - triggers = [ - pgtrigger.Trigger( - name="update_topology_geom", - operation=pgtrigger.Update | pgtrigger.Insert, - when=pgtrigger.After, - declare=[('stream_geom', 'geometry')], - func=""" - SELECT r.geom FROM river_stream r WHERE NEW.stream_id = r.id INTO stream_geom; - UPDATE description_morphology - SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position) - WHERE topology_id = NEW.id; - UPDATE description_status - SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position) - WHERE topology_id = NEW.id; - RETURN NEW; - """ - )] + # triggers = [ + # pgtrigger.Trigger( + # name="update_topology_geom", + # operation=pgtrigger.Update | pgtrigger.Insert, + # when=pgtrigger.After, + # declare=[('stream_geom', 'geometry')], + # func=""" + # SELECT r.geom FROM river_stream r WHERE NEW.stream_id = r.id INTO stream_geom; + # UPDATE description_morphology + # SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position) + # WHERE topology_id = NEW.id; + # UPDATE description_status + # SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position) + # WHERE topology_id = NEW.id; + # RETURN NEW; + # """ + # )] Study.add_property('stations', Station.within_buffer, _("Stations")) diff --git a/georiviere/river/sql/post_10_triggers.sql b/georiviere/river/sql/post_10_triggers.sql new file mode 100644 index 00000000..f83233af --- /dev/null +++ b/georiviere/river/sql/post_10_triggers.sql @@ -0,0 +1,43 @@ +CREATE TRIGGER river_stream_10_elevation +BEFORE INSERT OR UPDATE OF geom ON river_stream +FOR EACH ROW EXECUTE PROCEDURE elevation(); + +CREATE FUNCTION update_topology_geom() RETURNS trigger SECURITY DEFINER AS $$ +DECLARE + stream_geom geometry; +BEGIN + SELECT r.geom FROM river_stream r WHERE NEW.stream_id = r.id INTO stream_geom; + UPDATE description_morphology + SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position) + WHERE topology_id = NEW.id; + UPDATE description_status + SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position) + WHERE topology_id = NEW.id; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER core_path_10_elevation_iu_tgr +BEFORE INSERT OR UPDATE ON river_topology +FOR EACH ROW EXECUTE PROCEDURE update_topology_geom(); + +CREATE FUNCTION create_topologies() RETURNS trigger SECURITY DEFINER AS $$ +DECLARE + topology_morphology integer; + topology_status integer; +BEGIN + INSERT INTO river_topology (stream_id, start_position, end_position, qualified) + VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_morphology; + INSERT INTO description_morphology (topology_id, geom, description, date_insert, date_update) + VALUES (topology_morphology, NEW.geom, '', NOW(), NOW()); + INSERT INTO river_topology (stream_id, start_position, end_position, qualified) + VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_status; + INSERT INTO description_status (topology_id, geom, regulation, referencial, description, date_insert, date_update) + VALUES (topology_status, NEW.geom, FALSE, FALSE, '', NOW(), NOW()); + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER core_path_10_elevation_iu_tgr +AFTER INSERT ON river_stream +FOR EACH ROW EXECUTE PROCEDURE create_topologies(); \ No newline at end of file diff --git a/georiviere/river/sql/pre_10_cleanup.sql b/georiviere/river/sql/pre_10_cleanup.sql new file mode 100644 index 00000000..79b37e8f --- /dev/null +++ b/georiviere/river/sql/pre_10_cleanup.sql @@ -0,0 +1,3 @@ +DROP FUNCTION IF EXISTS update_topology_geom() CASCADE; +DROP FUNCTION IF EXISTS create_topologies() CASCADE; + diff --git a/georiviere/settings/__init__.py b/georiviere/settings/__init__.py index 00e4741c..56221baf 100644 --- a/georiviere/settings/__init__.py +++ b/georiviere/settings/__init__.py @@ -135,7 +135,7 @@ def construct_relative_path_mock(current_template_name, relative_name): 'embed_video', 'djgeojson', 'django_filters', - 'pgtrigger', + #'pgtrigger', 'compressor', 'mapentity', # mapentity should be placed after app declaring paperclip models 'leaflet', diff --git a/requirements.in b/requirements.in index c09d1eb1..a4d9353d 100644 --- a/requirements.in +++ b/requirements.in @@ -14,7 +14,6 @@ sentry-sdk django-admin-ordering djangorestframework-camel-case jsonschema -django-pgtrigger # Use until latest version of geotrek (> 2.99.0) drf-spectacular diff --git a/requirements.txt b/requirements.txt index 34e85eab..03f5a151 100644 --- a/requirements.txt +++ b/requirements.txt @@ -91,7 +91,6 @@ django==3.1.14 # django-leaflet # django-modeltranslation # django-mptt - # django-pgtrigger # django-querysetsequence # django-weasyprint # djangorestframework @@ -145,8 +144,6 @@ django-modeltranslation==0.17.3 # via mapentity django-mptt==0.11.0 # via geotrek -django-pgtrigger==4.11.0 - # via -r requirements.in django-querysetsequence==0.14 # via django-autocomplete-light django-tinymce==2.9.0 From dbd71b0d11341b60a324202542dddf6084244922 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Wed, 20 Dec 2023 14:20:09 +0100 Subject: [PATCH 12/26] use internal triggers --- georiviere/altimetry.py | 11 +++++++++++ georiviere/river/models.py | 31 ------------------------------- 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/georiviere/altimetry.py b/georiviere/altimetry.py index d36c1c74..9306f7e7 100644 --- a/georiviere/altimetry.py +++ b/georiviere/altimetry.py @@ -2,5 +2,16 @@ class AltimetryMixin(BaseAltimetryMixin): + def reload(self): + # Update object's computed values (reload from database) + if self.pk: + fromdb = self.__class__.objects.get(pk=self.pk) + BaseAltimetryMixin.reload(self, fromdb) + return self + + def save(self, *args, **kwargs): + super().save(*args, **kwargs) + self.reload() + class Meta: abstract = True diff --git a/georiviere/river/models.py b/georiviere/river/models.py index 041cab52..4aa38376 100644 --- a/georiviere/river/models.py +++ b/georiviere/river/models.py @@ -96,37 +96,6 @@ class FlowChoices(models.IntegerChoices): class Meta: verbose_name = _("Stream") verbose_name_plural = _("Streams") - # triggers = AltimetryMixin.Meta.triggers + [ - # pgtrigger.Trigger( - # name="create_topologies", - # operation=pgtrigger.Insert, - # declare=[ - # ('topology_morphology', 'integer'), - # ('topology_status', 'integer') - # ], - # when=pgtrigger.After, - # func=""" - # INSERT INTO river_topology (stream_id, start_position, end_position, qualified) - # VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_morphology; - # INSERT INTO description_morphology (topology_id, geom, description, date_insert, date_update) - # VALUES (topology_morphology, NEW.geom, '', NOW(), NOW()); - # INSERT INTO river_topology (stream_id, start_position, end_position, qualified) - # VALUES (NEW.id, 0, 1, FALSE) RETURNING id INTO topology_status; - # INSERT INTO description_status (topology_id, geom, regulation, referencial, description, date_insert, date_update) - # VALUES (topology_status, NEW.geom, FALSE, FALSE, '', NOW(), NOW()); - # RETURN NEW; - # """ - # ), - # pgtrigger.Trigger( - # name="update_topologies", - # operation=pgtrigger.UpdateOf('geom'), - # when=pgtrigger.After, - # func=""" - # UPDATE river_topology SET id=id WHERE stream_id=NEW.id; - # RETURN NEW; - # """ - # ) - # ] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) From 7099bbf3d5a07fd5429d1103d9f54aea621e23b9 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Wed, 20 Dec 2023 14:22:24 +0100 Subject: [PATCH 13/26] use internal triggers --- georiviere/altimetry.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/georiviere/altimetry.py b/georiviere/altimetry.py index 9306f7e7..fb32ca56 100644 --- a/georiviere/altimetry.py +++ b/georiviere/altimetry.py @@ -8,10 +8,10 @@ def reload(self): fromdb = self.__class__.objects.get(pk=self.pk) BaseAltimetryMixin.reload(self, fromdb) return self - + def save(self, *args, **kwargs): super().save(*args, **kwargs) self.reload() - + class Meta: abstract = True From 1b400a253e59e37bd89f8b78645eee09bcc0aedd Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Wed, 20 Dec 2023 14:30:17 +0100 Subject: [PATCH 14/26] use internal triggers --- georiviere/altimetry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/georiviere/altimetry.py b/georiviere/altimetry.py index fb32ca56..a4c58d43 100644 --- a/georiviere/altimetry.py +++ b/georiviere/altimetry.py @@ -11,7 +11,7 @@ def reload(self): def save(self, *args, **kwargs): super().save(*args, **kwargs) - self.reload() + self.reload(self) class Meta: abstract = True From 99ff1b3ae927887cfa2204552ebe45746d11f7c3 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Wed, 20 Dec 2023 14:31:46 +0100 Subject: [PATCH 15/26] use internal triggers --- georiviere/altimetry.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/georiviere/altimetry.py b/georiviere/altimetry.py index a4c58d43..1426eacf 100644 --- a/georiviere/altimetry.py +++ b/georiviere/altimetry.py @@ -6,12 +6,12 @@ def reload(self): # Update object's computed values (reload from database) if self.pk: fromdb = self.__class__.objects.get(pk=self.pk) - BaseAltimetryMixin.reload(self, fromdb) + super().reload(fromdb) return self def save(self, *args, **kwargs): super().save(*args, **kwargs) - self.reload(self) + self.reload() class Meta: abstract = True From 973d1348982f0a81a942a4219051811dea306d50 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Wed, 20 Dec 2023 14:32:08 +0100 Subject: [PATCH 16/26] use internal triggers --- georiviere/altimetry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/georiviere/altimetry.py b/georiviere/altimetry.py index 1426eacf..41d40b49 100644 --- a/georiviere/altimetry.py +++ b/georiviere/altimetry.py @@ -2,7 +2,7 @@ class AltimetryMixin(BaseAltimetryMixin): - def reload(self): + def reload(self, *args, **kwargs): # Update object's computed values (reload from database) if self.pk: fromdb = self.__class__.objects.get(pk=self.pk) From f02e638f2118a2969e94d0e40b29bdb29448b05c Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Wed, 20 Dec 2023 14:51:20 +0100 Subject: [PATCH 17/26] use internal triggers --- georiviere/altimetry.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/georiviere/altimetry.py b/georiviere/altimetry.py index 41d40b49..cf1d67ce 100644 --- a/georiviere/altimetry.py +++ b/georiviere/altimetry.py @@ -2,16 +2,16 @@ class AltimetryMixin(BaseAltimetryMixin): - def reload(self, *args, **kwargs): + def refresh(self): # Update object's computed values (reload from database) if self.pk: fromdb = self.__class__.objects.get(pk=self.pk) - super().reload(fromdb) + BaseAltimetryMixin.reload(fromdb) return self def save(self, *args, **kwargs): super().save(*args, **kwargs) - self.reload() + self.refresh() class Meta: abstract = True From fb86bd793318a79df581e0ee4fb83ada49a0c4f1 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Wed, 20 Dec 2023 14:59:29 +0100 Subject: [PATCH 18/26] use internal triggers --- georiviere/altimetry.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/georiviere/altimetry.py b/georiviere/altimetry.py index cf1d67ce..fb32ca56 100644 --- a/georiviere/altimetry.py +++ b/georiviere/altimetry.py @@ -2,16 +2,16 @@ class AltimetryMixin(BaseAltimetryMixin): - def refresh(self): + def reload(self): # Update object's computed values (reload from database) if self.pk: fromdb = self.__class__.objects.get(pk=self.pk) - BaseAltimetryMixin.reload(fromdb) + BaseAltimetryMixin.reload(self, fromdb) return self def save(self, *args, **kwargs): super().save(*args, **kwargs) - self.refresh() + self.reload() class Meta: abstract = True From 190dd0a1afeecb20941a6913c37592160f20b1c1 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Wed, 20 Dec 2023 15:07:47 +0100 Subject: [PATCH 19/26] use internal triggers --- georiviere/altimetry.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/georiviere/altimetry.py b/georiviere/altimetry.py index fb32ca56..f2bf5482 100644 --- a/georiviere/altimetry.py +++ b/georiviere/altimetry.py @@ -2,7 +2,7 @@ class AltimetryMixin(BaseAltimetryMixin): - def reload(self): + def refresh(self): # Update object's computed values (reload from database) if self.pk: fromdb = self.__class__.objects.get(pk=self.pk) @@ -11,7 +11,7 @@ def reload(self): def save(self, *args, **kwargs): super().save(*args, **kwargs) - self.reload() + self.refresh() class Meta: abstract = True From 111e06ded495db016c0c13b5cb50252687c459bb Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Wed, 20 Dec 2023 15:27:07 +0100 Subject: [PATCH 20/26] use internal triggers --- georiviere/description/sql/post_10_triggers.sql | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/georiviere/description/sql/post_10_triggers.sql b/georiviere/description/sql/post_10_triggers.sql index e801d311..25bdd79b 100644 --- a/georiviere/description/sql/post_10_triggers.sql +++ b/georiviere/description/sql/post_10_triggers.sql @@ -4,4 +4,8 @@ FOR EACH ROW EXECUTE PROCEDURE elevation(); CREATE TRIGGER description_status_10_elevation BEFORE INSERT OR UPDATE OF geom ON description_status +FOR EACH ROW EXECUTE PROCEDURE elevation(); + +CREATE TRIGGER description_land_10_elevation +BEFORE INSERT OR UPDATE OF geom ON description_land FOR EACH ROW EXECUTE PROCEDURE elevation(); \ No newline at end of file From e50be9da37bd6e1dab1af9465477ecf74db56ae6 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Wed, 20 Dec 2023 15:57:53 +0100 Subject: [PATCH 21/26] use internal triggers --- georiviere/description/models.py | 2 -- georiviere/description/sql/post_10_triggers.sql | 4 ++++ georiviere/proceeding/sql/post_10_triggers.sql | 3 +++ 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 georiviere/proceeding/sql/post_10_triggers.sql diff --git a/georiviere/description/models.py b/georiviere/description/models.py index 5be80af1..ca1aaaf2 100644 --- a/georiviere/description/models.py +++ b/georiviere/description/models.py @@ -199,7 +199,6 @@ class Morphology(AddPropertyBufferMixin, TopologyMixin, TimeStampedModelMixin, class Meta: verbose_name = _("Morphology") verbose_name_plural = _("Morphologies") - # triggers = AltimetryMixin.Meta.triggers def __str__(self): if self.main_flow: @@ -355,7 +354,6 @@ class Status(TopologyMixin, AddPropertyBufferMixin, TimeStampedModelMixin, Water class Meta: verbose_name = _("Status") verbose_name_plural = _("Statuses") - # triggers = AltimetryMixin.Meta.triggers def __str__(self): if self.status_types.count(): diff --git a/georiviere/description/sql/post_10_triggers.sql b/georiviere/description/sql/post_10_triggers.sql index 25bdd79b..958dbec4 100644 --- a/georiviere/description/sql/post_10_triggers.sql +++ b/georiviere/description/sql/post_10_triggers.sql @@ -8,4 +8,8 @@ FOR EACH ROW EXECUTE PROCEDURE elevation(); CREATE TRIGGER description_land_10_elevation BEFORE INSERT OR UPDATE OF geom ON description_land +FOR EACH ROW EXECUTE PROCEDURE elevation(); + +CREATE TRIGGER description_usage_10_elevation +BEFORE INSERT OR UPDATE OF geom ON description_usage FOR EACH ROW EXECUTE PROCEDURE elevation(); \ No newline at end of file diff --git a/georiviere/proceeding/sql/post_10_triggers.sql b/georiviere/proceeding/sql/post_10_triggers.sql new file mode 100644 index 00000000..fd0e2b8f --- /dev/null +++ b/georiviere/proceeding/sql/post_10_triggers.sql @@ -0,0 +1,3 @@ +CREATE TRIGGER proceeding_proceeding_10_elevation +BEFORE INSERT OR UPDATE OF geom ON proceeding_proceeding +FOR EACH ROW EXECUTE PROCEDURE elevation(); From d90e7751c6a6e81a3b938941e336c79554905581 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Wed, 3 Jan 2024 14:36:57 +0100 Subject: [PATCH 22/26] use internal triggers --- georiviere/altimetry.py | 2 ++ georiviere/description/sql/post_20_defaults.sql | 3 +++ georiviere/description/tests/test_views.py | 8 ++++---- georiviere/river/tests/test_models.py | 8 ++++---- georiviere/river/tests/test_signals.py | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) create mode 100644 georiviere/description/sql/post_20_defaults.sql diff --git a/georiviere/altimetry.py b/georiviere/altimetry.py index f2bf5482..cd7ee6b9 100644 --- a/georiviere/altimetry.py +++ b/georiviere/altimetry.py @@ -1,4 +1,5 @@ from geotrek.altimetry.models import AltimetryMixin as BaseAltimetryMixin +from geotrek.common.mixins import TimeStampedModelMixin class AltimetryMixin(BaseAltimetryMixin): @@ -7,6 +8,7 @@ def refresh(self): if self.pk: fromdb = self.__class__.objects.get(pk=self.pk) BaseAltimetryMixin.reload(self, fromdb) + TimeStampedModelMixin.reload(self, fromdb) return self def save(self, *args, **kwargs): diff --git a/georiviere/description/sql/post_20_defaults.sql b/georiviere/description/sql/post_20_defaults.sql new file mode 100644 index 00000000..5128eb1b --- /dev/null +++ b/georiviere/description/sql/post_20_defaults.sql @@ -0,0 +1,3 @@ +ALTER TABLE description_morphology ALTER COLUMN full_edge_height SET DEFAULT 0.0; +ALTER TABLE description_morphology ALTER COLUMN full_edge_width SET DEFAULT 0.0; +ALTER TABLE description_morphology ALTER COLUMN description SET DEFAULT ''; diff --git a/georiviere/description/tests/test_views.py b/georiviere/description/tests/test_views.py index 86940023..5e2b4f54 100644 --- a/georiviere/description/tests/test_views.py +++ b/georiviere/description/tests/test_views.py @@ -105,8 +105,8 @@ class SatusViewTestCase(TopologyTestCase): def get_expected_json_attrs(self): return { 'id': self.obj.pk, - 'date_update': '2020-03-17T00:00:00Z', - 'date_insert': '2020-03-17T00:00:00Z', + 'date_update': self.obj.date_update.isoformat().replace('+00:00', 'Z'), + 'date_insert': self.obj.date_insert.isoformat().replace('+00:00', 'Z'), 'description': '', 'length': self.obj.length, 'geom_3d': self.obj.geom_3d.ewkt, @@ -147,8 +147,8 @@ class MorphologyViewTestCase(TopologyTestCase): def get_expected_json_attrs(self): return { 'id': self.obj.pk, - 'date_update': '2020-03-17T00:00:00Z', - 'date_insert': '2020-03-17T00:00:00Z', + 'date_update': self.obj.date_update.isoformat().replace('+00:00', 'Z'), + 'date_insert': self.obj.date_insert.isoformat().replace('+00:00', 'Z'), 'description': '', 'bank_state_left': None, 'bank_state_right': None, diff --git a/georiviere/river/tests/test_models.py b/georiviere/river/tests/test_models.py index d37a240e..69c8ac89 100644 --- a/georiviere/river/tests/test_models.py +++ b/georiviere/river/tests/test_models.py @@ -90,16 +90,16 @@ def test_get_map_image_extent(self): self.assertAlmostEqual(lat_max, -5.655019875165679) def test_distance_to_source(self): - """Test distance from a given object to stream source according to differents geom""" + """Test distance from a given object to stream source according to different geom""" self.assertAlmostEqual(self.stream1.distance_to_source(self.usage_point), 28.2842712) self.assertEqual(self.stream1.distance_to_source(self.administrative_file), None) - self.assertEqual(DistanceToSource.objects.count(), 6) + self.assertEqual(DistanceToSource.objects.count(), 2) usage_point = UsageFactory.create( geom=Point(10000, 10010) ) - self.assertEqual(DistanceToSource.objects.count(), 8) + self.assertEqual(DistanceToSource.objects.count(), 4) usage_point.delete() - self.assertEqual(DistanceToSource.objects.count(), 6) + self.assertEqual(DistanceToSource.objects.count(), 2) class SnapTest(TestCase): diff --git a/georiviere/river/tests/test_signals.py b/georiviere/river/tests/test_signals.py index 148669ad..f947d67d 100644 --- a/georiviere/river/tests/test_signals.py +++ b/georiviere/river/tests/test_signals.py @@ -30,5 +30,5 @@ def test_update_stream_move_topologies(self): morphologies = Morphology.objects.values_list('geom', flat=True) status = Status.objects.values_list('geom', flat=True) - self.assertEqual(morphologies[0], morphologies[1]) + self.assertEqual(morphologies[0], morphologies[1], f"{morphologies[0].ewkt} - {morphologies[1].ewkt}", ) self.assertEqual(status[0], status[1]) From 93bf9ba69645524db0ead9cdc14a9068316ef65a Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Wed, 28 Feb 2024 10:30:12 +0100 Subject: [PATCH 23/26] use internal triggers --- georiviere/main/apps.py | 1 + georiviere/main/signals.py | 3 ++- georiviere/settings/__init__.py | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/georiviere/main/apps.py b/georiviere/main/apps.py index 3cb9f0b9..8e84238c 100644 --- a/georiviere/main/apps.py +++ b/georiviere/main/apps.py @@ -15,5 +15,6 @@ def ready(self): from georiviere.river.models import Stream for model in apps.get_models(): if issubclass(model, MapEntityMixin) and model != Stream: + print("signal for model {}".format(model)) post_save.connect(signals.save_objects_generate_distance_to_source, sender=model) post_delete.connect(signals.delete_objects_remove_distance_to_source, sender=model) diff --git a/georiviere/main/signals.py b/georiviere/main/signals.py index f10be4a8..e2c2aa74 100644 --- a/georiviere/main/signals.py +++ b/georiviere/main/signals.py @@ -45,7 +45,8 @@ def save_objects_generate_distance_to_source(sender, instance, **kwargs): ).exclude(stream__in=streams).delete() elif hasattr(instance, 'topology'): - stream = annotate_distance_to_source(Stream.objects.all(), instance).get(pk=instance.topology.stream.pk) + raise Exception("yes") + stream = annotate_distance_to_source(Stream.objects.all(), instance).get(pk=instance.topology.stream_id) DistanceToSource.objects.update_or_create( object_id=instance.pk, content_type=ContentType.objects.get_for_model(instance._meta.model), diff --git a/georiviere/settings/__init__.py b/georiviere/settings/__init__.py index 56221baf..4daf8d0f 100644 --- a/georiviere/settings/__init__.py +++ b/georiviere/settings/__init__.py @@ -135,7 +135,6 @@ def construct_relative_path_mock(current_template_name, relative_name): 'embed_video', 'djgeojson', 'django_filters', - #'pgtrigger', 'compressor', 'mapentity', # mapentity should be placed after app declaring paperclip models 'leaflet', From 7f8d61caa067407c5bc8671edc95dffe893a72d3 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Wed, 28 Feb 2024 10:56:50 +0100 Subject: [PATCH 24/26] use internal triggers --- georiviere/main/signals.py | 1 - 1 file changed, 1 deletion(-) diff --git a/georiviere/main/signals.py b/georiviere/main/signals.py index e2c2aa74..758e1bf2 100644 --- a/georiviere/main/signals.py +++ b/georiviere/main/signals.py @@ -45,7 +45,6 @@ def save_objects_generate_distance_to_source(sender, instance, **kwargs): ).exclude(stream__in=streams).delete() elif hasattr(instance, 'topology'): - raise Exception("yes") stream = annotate_distance_to_source(Stream.objects.all(), instance).get(pk=instance.topology.stream_id) DistanceToSource.objects.update_or_create( object_id=instance.pk, From 18617915263b56896186ab1583e6bbc10d665d26 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Thu, 11 Apr 2024 09:54:39 +0200 Subject: [PATCH 25/26] fix command --- georiviere/contribution/schema.py | 79 ++++++++++--------- .../river/management/commands/load_rivers.py | 19 +++-- georiviere/river/managers.py | 6 ++ georiviere/river/models.py | 20 +---- georiviere/utils/__init__.py | 0 georiviere/utils/mixins/managers.py | 7 ++ 6 files changed, 70 insertions(+), 61 deletions(-) create mode 100644 georiviere/river/managers.py create mode 100644 georiviere/utils/__init__.py create mode 100644 georiviere/utils/mixins/managers.py diff --git a/georiviere/contribution/schema.py b/georiviere/contribution/schema.py index 0c85d301..1315881c 100644 --- a/georiviere/contribution/schema.py +++ b/georiviere/contribution/schema.py @@ -7,9 +7,9 @@ InvasiveSpecies, HeritageSpecies, HeritageObservation, FishSpecies, NaturePollution, TypePollution) -# The json schema is summarize on : +# The json schema is summarized on : # https://github.com/Georiviere/Georiviere-admin/issues/139 -# Depending of the category and type of the contributions, some fields are available or not. +# Depending on the category and type of the contributions, some fields are available or not. # Here is the generation of the json schema used by the website portal. # The fields available depending on the type of contributions follow the documentation of jsonschema : # https://json-schema.org/understanding-json-schema/reference/conditionals.html @@ -18,37 +18,43 @@ def get_contribution_properties(): """ Feature properties as form initial data format (name / value) """ # TODO: Use directly field definition for type / title / max length - results = {'name_author': { - 'type': "string", - 'title': _("Name author"), - "maxLength": 128 - }, 'first_name_author': { - 'type': "string", - 'title': _("First name author"), - "maxLength": 128 - }, 'email_author': { - 'type': "string", - 'title': _("Email"), - 'format': "email" - }, 'date_observation': { - 'type': "string", - 'title': _("Observation's date"), - 'format': 'date' - }, 'description': { - 'type': "string", - 'title': _('Description') - }, 'category': { - "type": "string", - "title": _("Category"), - # TODO: Loop on contribution one to one field to get all possibilities - "enum": [ - str(ContributionQuantity._meta.verbose_name.title()), - str(ContributionQuality._meta.verbose_name.title()), - str(ContributionFaunaFlora._meta.verbose_name.title()), - str(ContributionLandscapeElements._meta.verbose_name.title()), - str(ContributionPotentialDamage._meta.verbose_name.title()) - ], - } + results = { + 'name_author': { + 'type': "string", + 'title': _("Name author"), + "maxLength": 128 + }, + 'first_name_author': { + 'type': "string", + 'title': _("First name author"), + "maxLength": 128 + }, + 'email_author': { + 'type': "string", + 'title': _("Email"), + 'format': "email" + }, + 'date_observation': { + 'type': "string", + 'title': _("Observation's date"), + 'format': 'date' + }, + 'description': { + 'type': "string", + 'title': _('Description') + }, + 'category': { + "type": "string", + "title": _("Category"), + # TODO: Loop on contribution one to one field to get all possibilities + "enum": [ + str(ContributionQuantity._meta.verbose_name.title()), + str(ContributionQuality._meta.verbose_name.title()), + str(ContributionFaunaFlora._meta.verbose_name.title()), + str(ContributionLandscapeElements._meta.verbose_name.title()), + str(ContributionPotentialDamage._meta.verbose_name.title()) + ], + } } if SeverityType.objects.exists(): results['severity'] = { @@ -110,8 +116,7 @@ def get_disruptive_jam(choices, meta): 'jam_type': { 'type': "string", - 'title': str(meta.get_field( - 'jam_type').related_model._meta.verbose_name.capitalize()), + 'title': str(meta.get_field('jam_type').related_model._meta.verbose_name.capitalize()), 'enum': list(JamType.objects.values_list('label', flat=True)) } }, @@ -125,7 +130,9 @@ def get_bank_erosion(choices, meta): 'if': { 'properties': { 'type': { - 'const': str(choices.BANK_EROSION.label)}} + 'const': str(choices.BANK_EROSION.label) + } + } }, 'then': { 'properties': { diff --git a/georiviere/river/management/commands/load_rivers.py b/georiviere/river/management/commands/load_rivers.py index 07b1acca..905c4983 100644 --- a/georiviere/river/management/commands/load_rivers.py +++ b/georiviere/river/management/commands/load_rivers.py @@ -15,8 +15,10 @@ def add_arguments(self, parser): parser.add_argument('file_path', help="File's path to import.") parser.add_argument('--name-attribute', '-n', action='store', dest='name', default='nom', help="Attribute name in file to use as river name") - parser.add_argument('--flush-streams', '-f', action='store_true', dest='flush', default=False, - help="Flush current streams") + parser.add_argument('--flush', '-f', action='store_true', dest='flush', default=False, + help="Flush rivers before import.") + parser.add_argument('--batch-size', '-bs', action='store', dest='batch_size', default=50, + help="Size of batch to use for bulk_create. Default is 50.") parser.add_argument('--default-name-attribute', '-nd', action='store', dest='default_name', default=_('River'), help="Default name to use if attribute name specified is empty") @@ -25,17 +27,17 @@ def handle(self, *args, **options): name_column = options.get('name') default_name = options.get('default_name') flush = options.get('flush') + batch_size = options.get('batch_size') data_source = DataSource(file_path) layer = data_source[0] total_count = len(layer) + self.stdout.write(f"Load rivers: {total_count} features to import") if flush: self.stdout.write("Delete streams.....", ending="") - Stream.objects.all().delete() + Stream.objects.truncate() self.stdout.write(self.style.SUCCESS("done!")) - batch_size = 50 - objs = (Stream(geom=feat.geom.geos, source_location=Point(feat.geom.geos[0]), name=feat.get(name_column) or default_name) for feat in layer) @@ -46,7 +48,10 @@ def handle(self, *args, **options): if not batch: break self.stdout.write(f"{count} / {total_count}", ending="") - Stream.objects.bulk_create(batch, batch_size) - self.stdout.write(self.style.SUCCESS(" ok!")) + try: + Stream.objects.bulk_create(batch, batch_size) + self.stdout.write(self.style.SUCCESS(" ok!")) + except Exception as e: + self.stdout.write(self.style.ERROR(" error!")) self.stdout.write(self.style.SUCCESS(f"Successfully import {total_count} rivers and associated morphologies / status")) diff --git a/georiviere/river/managers.py b/georiviere/river/managers.py new file mode 100644 index 00000000..b3060af7 --- /dev/null +++ b/georiviere/river/managers.py @@ -0,0 +1,6 @@ +from django.db import models +from georiviere.utils.mixins.managers import TruncateManagerMixin + + +class RiverManager(TruncateManagerMixin, models.Manager): + pass diff --git a/georiviere/river/models.py b/georiviere/river/models.py index 4aa38376..af65cd85 100644 --- a/georiviere/river/models.py +++ b/georiviere/river/models.py @@ -25,6 +25,7 @@ from georiviere.observations.models import Station from georiviere.proceeding.models import Proceeding from georiviere.maintenance.models import Intervention +from georiviere.river.managers import RiverManager from georiviere.studies.models import Study from georiviere.watershed.mixins import WatershedPropertiesMixin @@ -90,7 +91,7 @@ class FlowChoices(models.IntegerChoices): portals = models.ManyToManyField('portal.Portal', blank=True, related_name='streams', verbose_name=_("Published portals")) - + objects = RiverManager() capture_map_image_waitfor = '.other_object_enum_loaded' class Meta: @@ -219,23 +220,6 @@ def __str__(self): class Meta: verbose_name = _("Topology") verbose_name_plural = _("Topologies") - # triggers = [ - # pgtrigger.Trigger( - # name="update_topology_geom", - # operation=pgtrigger.Update | pgtrigger.Insert, - # when=pgtrigger.After, - # declare=[('stream_geom', 'geometry')], - # func=""" - # SELECT r.geom FROM river_stream r WHERE NEW.stream_id = r.id INTO stream_geom; - # UPDATE description_morphology - # SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position) - # WHERE topology_id = NEW.id; - # UPDATE description_status - # SET geom = ST_LINESUBSTRING(stream_geom, NEW.start_position, NEW.end_position) - # WHERE topology_id = NEW.id; - # RETURN NEW; - # """ - # )] Study.add_property('stations', Station.within_buffer, _("Stations")) diff --git a/georiviere/utils/__init__.py b/georiviere/utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/georiviere/utils/mixins/managers.py b/georiviere/utils/mixins/managers.py new file mode 100644 index 00000000..afb01020 --- /dev/null +++ b/georiviere/utils/mixins/managers.py @@ -0,0 +1,7 @@ +from django.db import connection + + +class TruncateManagerMixin: + def truncate(self): + with connection.cursor() as cursor: + cursor.execute('TRUNCATE TABLE "{0}" CASCADE'.format(self.model._meta.db_table)) From d4b75ca5cdb13af356109f453e7e2fc6a305cb45 Mon Sep 17 00:00:00 2001 From: J-E Castagnede Date: Thu, 11 Apr 2024 09:55:58 +0200 Subject: [PATCH 26/26] lint --- georiviere/river/management/commands/load_rivers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/georiviere/river/management/commands/load_rivers.py b/georiviere/river/management/commands/load_rivers.py index 905c4983..38a8668c 100644 --- a/georiviere/river/management/commands/load_rivers.py +++ b/georiviere/river/management/commands/load_rivers.py @@ -51,7 +51,7 @@ def handle(self, *args, **options): try: Stream.objects.bulk_create(batch, batch_size) self.stdout.write(self.style.SUCCESS(" ok!")) - except Exception as e: + except Exception: self.stdout.write(self.style.ERROR(" error!")) self.stdout.write(self.style.SUCCESS(f"Successfully import {total_count} rivers and associated morphologies / status"))