Migration optimizer does not optimize choices

We have a lot of tables in our db which have a lot of category-type fields, and those charfields have a fixed set of choices that have been growing in the history of the project.

First migration:

        migrations.CreateModel(
            name="...",
            fields=[...
                (
                    "transaction_type",
                    models.CharField(
                        blank=True,
                        choices=[
                            ("DD_FIRST_COLLECTION", "Direct debit first collection"),
                            ("DD_REGULAR_COLLECTION", "Direct debit regular collection"),
                        ],
                        max_length=512,
                    ),
                ),

And lots of these:

        migrations.AlterField(
            model_name="accountpayment",
            name="transaction_type",
            field=models.CharField(
                blank=True,
                choices=[
                    ("DD_FIRST_COLLECTION", "Direct debit first collection"),
                    ("DD_REGULAR_COLLECTION", "Direct debit regular collection"),
                    ("CREDIT_CARD", "Credit card collection"),
....

I think the right behaviour, during squashmigrations, should be that the migrations optimizer merges these operations back into one. Especially if the second set is a superset of the first one.

Could this be a suggested improvement to the optimizer’s code? or is there a edge case which i am not seeing?

The problem - and the reason choices are there in the first place - is that the optimiser doesn’t know if choices is relevant or not (it’s the same with any field argument), and so it can’t do special handling just for it.

If we could trust that choices didn’t affect the database - which it doesn’t in almost all situations - then it would be fine. In your case, it probably is - but I don’t think we could turn that setting turned on by default.

The right approach here might be pluggable optimiser strategies that allow people to opt-in to certain fields not affecting the DB or being last-value-wins, like this.