BezBartek / django-db-views

Creating automatic migrations for Views models witch working reverse and full command options like in normal makemigrations
MIT License
62 stars 12 forks source link

Respect `migrations.SeparateDatabaseAndState` #31

Closed ckoppelman closed 6 months ago

ckoppelman commented 6 months ago

Currently, the autodetector is only evaluating the database state based on ViewRunPython, but doesn't account for ViewRunPython classes that are withinmigrations.SeparateDatabaseAndState. (see autodetector.ViewMigrationAutoDetector#get_previous_view_definition_state:260)

If I do not include state operations, the normal makemigrations command will create an additional migration for me, which I'd prefer to add to my view migration.

For instance, the following migration does not register even though it should. If I have this migration and run manage.py makeviewmigrations, it will add a new migration that recreates my_view:

class Migration(migrations.Migration):
    dependencies = [

    ]

    operations = [
        migrations.SeparateDatabaseAndState(
            database_operations=[
                django_db_views.operations.ViewRunPython(
                    code=django_db_views.migration_functions.ForwardMaterializedViewMigration(
                        "SELECT id FROM my_table",
                        "my_view",
                        engine="django.db.backends.postgresql",
                    ),
                    reverse_code=BackwardMaterializedViewMigration(
                        "",
                        "my_view",
                        engine="django.db.backends.postgresql",
                    ),
                    atomic=False,
                ),
            ],
            state_operations=[
                migrations.CreateModel(
                    name="MyView",
                    fields=[
                        (
                            "id",
                            models.OneToOneField(
                                on_delete=models.deletion.DO_NOTHING,
                                primary_key=True,
                                serialize=False,
                                to="my_app.MyTable",
                            ),
                        ),
                    ],
                    options={"managed": False, "db_table": "my_view"},
                ),
            ],
        )
    ]

My workaround is to add a simple state migration alongside the view migration.

An alternative fix would be to allow for state_operation changes within the view migration, but I think the SeparateDatabaseAndState migrations should be supported, minimally, in order to behave like the standard migrations.

ckoppelman commented 6 months ago

As a side note, it would be awesome if instead of analyzing this by class, you could analyze this by generated SQL in order to account for straight SQL migrations. I think that's a step above and beyond, though.

BezBartek commented 6 months ago

@ckoppelman Thank you for your comment and pointing it out.

Initially, I will add support, to be able to include/read state from SeparateDatabaseAndState operations, so it would be no problem if you would wrap ViewRunPython into it manually. I think it would solve your issue. I will deliver this in the coming week (I started today, I need to add some tests for it).

In future versions, I will try to think how to refactor lib, to generate migrations with SeparateDatabaseAndState operations that included model creation instead of raw ViewRunPython operations.

I hope it is fine for you, unfortunately I do not have enough time, to do it at once

BezBartek commented 6 months ago

@ckoppelman I published new version on PyPi https://pypi.org/project/django-db-views/

for next iteration of SeparateDatabaseAndState I will create separate issue