3YOURMIND/django-deprecate-fields

Deprecate a whole model?

Opened this issue · 1 comments

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)

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?