Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate a whole model? #31

Open
soerface opened this issue Jul 10, 2024 · 1 comment
Open

Deprecate a whole model? #31

soerface opened this issue Jul 10, 2024 · 1 comment

Comments

@soerface
Copy link

Do you have any experience deprecating a whole model, not just a field? What I tried is to deprecate and then remove every field, so now I'm left with:

class MyModel(models.Model):
    pass

Still, this for some reason makes the Django ORM still issue queries in the form of SELECT "my_model"."id" FROM "my_model" ORDER BY "my_model"."id" ASC, seemingly for every test that is marked with the @pytest.mark.django_db decorator.

(Background: The CI pipeline is making a migration to the latest DB version, i.e. a revision where I dropped MyModel, and then executing the test suite of the previous software version, i.e. with the model still in place, to make sure that the previous version can run on the latest schema. This enforces us to always use deprecate_field(...) before dropping a column, but now I'm left without a clue how to apply this on a model level)

@soerface
Copy link
Author

We managed to solve this in the following way:

Step 1

Configure the model to be unmanaged by Django:

class MyModel(models.Model):

    class Meta:
        managed = False

Create a migration as usual via makemigrations. It will contain the operation migrations.AlterModelOptions(name='mymodel', options={'managed': False},),. Rollout / run migrations

Step 2

Delete the model. Run makemigrations. It will look like this:

    operations = [
        migrations.DeleteModel(
            name='MyModel',
        ),
    ]

Modify the generated migration! If you leave it like this, you will just get rid of the Python code, but not the tables. Checkout this stackoverflow answer and the comments below it.
To also get rid of the table, alter your migration to make the model managed again, right before you delete it:

from django.db import migrations


class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '1234_alter_mymodel_options'),
    ]

    operations = [
        migrations.AlterModelOptions(
            name='mymodel',
            options={'managed': True},
        ),
        migrations.DeleteModel(
            name='MyModel',
        ),
    ]

You can roll this out and run migrations as usual. The previous software version can handle the missing table, since it is already marked as unmanaged, and the new version will take care of dropping the table.


Do you think this process can be simplified with the help of django-deprecate-fields / would it be in the scope of this package? From a user perspective, I could imagine that it would be nice to be able to decorate the model definition with a @deprecate_model. The decorator could set the managed attribute, but I'm not sure if it would also be able to modify the second migration accordingly to take care of deleting the model. What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant