Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django migration drops and re-adds same constraint

Asking for a friend... Can anybody explain why my Django migration is dropping and re-adding the exact same constraint on my table column when I add blank=True to the model field? Here's my change in my model:

# old definition
class CatalogCourse(models.Model):
    subjects = models.ManyToManyField(CatalogSubject, related_name="catalog_course_set")

# new definition with `blank=True`
class CatalogCourse(models.Model):
    subjects = models.ManyToManyField(CatalogSubject, related_name="catalog_course_set", blank=True)

When I makemigrations, I get this migration:

class Migration(migrations.Migration):

    dependencies = [
        ('homepage', '0005_previous_migration'),
    ]

    operations = [
        migrations.AlterField(
            model_name='catalogcourse',
            name='subjects',
            field=models.ManyToManyField(blank=True, related_name='catalog_course_set', to='homepage.CatalogSubject'),
        ),
    ]

The SQL for this migration is simply:

BEGIN;
--
-- Alter field subjects on catalogcourse
--
ALTER TABLE "homepage_catalogcourse_subjects" DROP CONSTRAINT "homepa_catalogsubject_id_304824f4_fk_homepage_catalogsubject_id";
ALTER TABLE "homepage_catalogcourse_subjects" ADD CONSTRAINT "homepa_catalogsubject_id_304824f4_fk_homepage_catalogsubject_id" FOREIGN KEY ("catalogsubject_id") REFERENCES "homepage_catalogsubject" ("id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "homepage_catalogcourse_subjects" DROP CONSTRAINT "homepage_catalogcourse_id_cc699e39_fk_homepage_catalogcourse_id";
ALTER TABLE "homepage_catalogcourse_subjects" ADD CONSTRAINT "homepage_catalogcourse_id_cc699e39_fk_homepage_catalogcourse_id" FOREIGN KEY ("catalogcourse_id") REFERENCES "homepage_catalogcourse" ("id") DEFERRABLE INITIALLY DEFERRED;
COMMIT;

Is Django just built to drop a constraint and re-add it anytime we alter the field? I can't think of any reason why that would need to happen? Are there operations that can't be performed while a foreign key constraint exists?

like image 957
ngoue Avatar asked Nov 02 '25 00:11

ngoue


2 Answers

If looks like you are hitting the bug described in ticket 25253.

like image 81
Alasdair Avatar answered Nov 03 '25 14:11

Alasdair


If you cannot afford the downtime, use a ​RunSQL migration operation with state_operations as a workaround. This will tell Django: running this SQL will be equivalent to these operations in terms of database state. Example:

migrations.RunSQL(
   """--
   -- Alter field trip on payment
   --
   ALTER TABLE "myapp_payment" ALTER COLUMN "trip_id" DROP NOT NULL;
   """,
   state_operations=[
       migrations.AlterField(
           model_name='payment',
           name='trip',
           field=models.ForeignKey(blank=True, null=True,
                                   on_delete=django.db.models.deletion.PROTECT,
                                   related_name='payments', to='myapp.Trip'),
       ),
   ])

This way we only apply the SQL we want and Django won't complain about the migration state not matching the current model. :)

like image 32
dukebody Avatar answered Nov 03 '25 15:11

dukebody



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!