From 6cda6f087a53b4e67642eb26494d02fabd1cdd4d Mon Sep 17 00:00:00 2001 From: etj Date: Tue, 7 Mar 2023 17:40:51 +0100 Subject: [PATCH] #99 Port to GeoNode 4 - fix migrations --- rndt/migrations/0003_layerrndt.py | 92 +++++++------------- rndt/migrations/0004_layerrndt_resolution.py | 40 ++++++--- rndt/migrations/0005_layerrndt_accuracy.py | 42 ++++++--- rndt/migrations/0006_layerrndt.py | 51 +++++++++++ rndt/migrations/__init__.py | 26 ++++++ 5 files changed, 168 insertions(+), 83 deletions(-) create mode 100644 rndt/migrations/0006_layerrndt.py diff --git a/rndt/migrations/0003_layerrndt.py b/rndt/migrations/0003_layerrndt.py index 207bb3c..a497044 100644 --- a/rndt/migrations/0003_layerrndt.py +++ b/rndt/migrations/0003_layerrndt.py @@ -1,79 +1,49 @@ # Generated by Django 2.2.16 on 2021-02-17 10:57 import logging -import django.db.models.deletion +from django.db.models.deletion import CASCADE from django.db import migrations, models -from django.db import DatabaseError -from django.db import connections -from django.db.migrations.recorder import MigrationRecorder logger = logging.getLogger(__name__) - -def migration_applied(app_label: str, migration_name: str) -> bool: - for alias in connections: - try: - if (MigrationRecorder.Migration.objects - .using(alias) - .filter(app=app_label, name=migration_name) - .exists()): - return True - except DatabaseError as e: - # django_migrations table does not exist -> no migrations applied - logger.info("Error retrieving migrations", exc_info=e) - pass - - return False - - try: from geonode.layers.models import Layer - logger.debug("Linking LayerRNDT to Layer (<4.x)") + logger.error("Linking LayerRNDT to Layer (<4.x) -- we're not supposed to be here!") + # we're on branch 4.x and should not have the Layer class, anyway here it is + # we can't iuse this model in 4.x bc class Layer does not exist anymore + + class Migration(migrations.Migration): + dependencies = [ + ('rndt', '0001_initial'), + ('layers', '24_initial') + ] + + operations = [ + migrations.CreateModel( + name='LayerRNDT', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('constraints_other', models.TextField(default=None, null=True)), + ('layer', models.OneToOneField(on_delete=CASCADE, to='layers.Layer')), + ], + options={ + 'verbose_name_plural': 'Layer RNDT', + 'ordering': ('layer', 'constraints_other'), + }, + ), + ] - fk_pointed_class = 'layers.Layer' - base_dep = ('layers', '24_initial') except ImportError: try: from geonode.layers.models import Dataset - logger.debug("Linking LayerRNDT to Dataset (>=4.x)") - fk_pointed_class = 'layers.Dataset' + logger.debug("Deferring LayerRNDT creation on geonode>=4.x)") + # when running on 4.x, we're going to deal with the RNDTLayer model in a brand new migration (0006) + + class Migration(migrations.Migration): + dependencies = [('rndt', '0001_initial'), ] + operations = [migrations.RunPython(migrations.RunPython.noop, migrations.RunPython.noop)] - if migration_applied('rndt', '0003_layerrndt'): - # RNDT already installed in 3.3.x - we're migrating from 3.3 to 4.x - # we're not supposed to do anything in the DB, since the table is already there, - # and the FK will be automatically migrated in the renaming in 0038_rename_layer_dataset. - # We can't put 0038_rename_layer_dataset as a dependency or we'll get: - # -- django.db.migrations.exceptions.InconsistentMigrationHistory: Migration rndt.0003_layerrndt is applied - # -- before its dependency layers.0038_rename_layer_dataset on database 'default'. - base_dep = None - else: - # we need the dataset table created by the base migration - base_dep = ('layers', '0038_rename_layer_dataset') - logger.debug(f"Depending on {base_dep}") except ImportError: raise Exception('Can not find base class for LayerRNDT') -class Migration(migrations.Migration): - - dependencies = [ - ('rndt', '0001_initial'), - ] - - if base_dep: - dependencies.append(base_dep) - - operations = [ - migrations.CreateModel( - name='LayerRNDT', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('constraints_other', models.TextField(default=None, null=True)), - ('layer', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=fk_pointed_class)), - ], - options={ - 'verbose_name_plural': 'Layer RNDT', - 'ordering': ('layer', 'constraints_other'), - }, - ), - ] diff --git a/rndt/migrations/0004_layerrndt_resolution.py b/rndt/migrations/0004_layerrndt_resolution.py index 368474b..c36332f 100644 --- a/rndt/migrations/0004_layerrndt_resolution.py +++ b/rndt/migrations/0004_layerrndt_resolution.py @@ -1,18 +1,36 @@ # Generated by Django 2.2.16 on 2021-02-24 18:05 +import logging from django.db import migrations, models +logger = logging.getLogger(__name__) -class Migration(migrations.Migration): +try: + from geonode.layers.models import Layer + logger.error("Linking LayerRNDT to Layer (<4.x) -- we're not supposed to be here!") + class Migration(migrations.Migration): - dependencies = [ - ('rndt', '0003_layerrndt'), - ] + dependencies = [ + ('rndt', '0003_layerrndt'), + ] + + operations = [ + migrations.AddField( + model_name='layerrndt', + name='resolution', + field=models.FloatField(default=None, null=True), + ), + ] +except ImportError: + try: + from geonode.layers.models import Dataset + logger.debug("Deferring LayerRNDT creation on geonode>=4.x)") + # when running on 4.x, we're going to deal with the RNDTLayer model in a brand new migration (0006) + + class Migration(migrations.Migration): + dependencies = [('rndt', '0003_layerrndt'),] + operations = [migrations.RunPython(migrations.RunPython.noop, migrations.RunPython.noop)] + + except ImportError: + raise Exception('Can not find base class for LayerRNDT') - operations = [ - migrations.AddField( - model_name='layerrndt', - name='resolution', - field=models.FloatField(default=None, null=True), - ), - ] diff --git a/rndt/migrations/0005_layerrndt_accuracy.py b/rndt/migrations/0005_layerrndt_accuracy.py index 5433cb0..30db914 100644 --- a/rndt/migrations/0005_layerrndt_accuracy.py +++ b/rndt/migrations/0005_layerrndt_accuracy.py @@ -1,18 +1,38 @@ # Generated by Django 2.2.16 on 2021-02-25 16:27 +import logging from django.db import migrations, models +logger = logging.getLogger(__name__) -class Migration(migrations.Migration): +try: + from geonode.layers.models import Layer + logger.error("Linking LayerRNDT to Layer (<4.x) -- we're not supposed to be here!") - dependencies = [ - ('rndt', '0004_layerrndt_resolution'), - ] + class Migration(migrations.Migration): + + dependencies = [ + ('rndt', '0004_layerrndt_resolution'), + ] + + operations = [ + migrations.AddField( + model_name='layerrndt', + name='accuracy', + field=models.FloatField(default=None, null=True), + ), + ] + +except ImportError: + try: + from geonode.layers.models import Dataset + logger.debug("Deferring LayerRNDT creation on geonode>=4.x)") + # when running on 4.x, we're going to deal with the RNDTLayer model in a brand new migration (0006) + + class Migration(migrations.Migration): + dependencies = [('rndt', '0004_layerrndt_resolution'),] + operations = [migrations.RunPython(migrations.RunPython.noop, migrations.RunPython.noop)] + + except ImportError: + raise Exception('Can not find base class for LayerRNDT') - operations = [ - migrations.AddField( - model_name='layerrndt', - name='accuracy', - field=models.FloatField(default=None, null=True), - ), - ] diff --git a/rndt/migrations/0006_layerrndt.py b/rndt/migrations/0006_layerrndt.py new file mode 100644 index 0000000..417d62f --- /dev/null +++ b/rndt/migrations/0006_layerrndt.py @@ -0,0 +1,51 @@ +# Generated by Django 3.2.16 on 2023-03-07 14:58 + +from django.db import migrations, models, connection +import django.db.models.deletion + +# common model operation +create_model_operation = migrations.CreateModel( + name='LayerRNDT', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('constraints_other', models.TextField(default=None, null=True)), + ('resolution', models.FloatField(default=None, null=True)), + ('accuracy', models.FloatField(default=None, null=True)), + ('layer', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='layers.dataset')), + ], + options={ + 'verbose_name_plural': 'Layer RNDT', + 'ordering': ('layer', 'constraints_other'), + }, +) + +# We're going to deal with both +# - MIGRATION from 3.3 +# - we already have the table in the DB, +# - we modified the previous migration in order to have noop operations for each RNDT migration, so we'll have to deal +# with the model stuff here +# - the db change is only related to a FK table (was layers_layer, become layers_dataset), but this change in db +# is automatically performed by the DBMS once the table is renamed (migration '0038_rename_layer_dataset'). +# - CREATION in 4.x +# - we are going to deal with both db and django state here + +if 'rndt_layerrndt' not in connection.introspection.table_names(): + # we don't have the table in the DB: let's have a complete (state+db) Model + ops = [create_model_operation, ] +else: + # we do have the table in the DB, so we need to synch the Model state only + ops = [ + migrations.SeparateDatabaseAndState( + state_operations=[create_model_operation, ], + database_operations=[] + ) + ] + + +class Migration(migrations.Migration): + dependencies = [ + ('layers', '0038_rename_layer_dataset'), + ('rndt', '0005_layerrndt_accuracy'), + ] + + operations = ops diff --git a/rndt/migrations/__init__.py b/rndt/migrations/__init__.py index e69de29..58b5785 100644 --- a/rndt/migrations/__init__.py +++ b/rndt/migrations/__init__.py @@ -0,0 +1,26 @@ +import logging + +from django.db import DatabaseError, connections +from django.db.migrations.recorder import MigrationRecorder + +logger = logging.getLogger(__name__) + + +def migration_applied(app_label: str, migration_name: str) -> bool: + + for alias in connections: + try: + if ( + MigrationRecorder.Migration.objects.using(alias) + .filter(app=app_label, name=migration_name) + .exists() + ): + logger.info("MIGRATION EXIST") + return True + except DatabaseError as e: + # django_migrations table does not exist -> no migrations applied + logger.info("ERROR RETRIEVING MIGRATIONS ", exc_info=e) + pass + + logger.info("MIGRATION DOES NOT EXIST") + return False