﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
36779	DeleteModel can lead to missing FK constraints	Jamie Cockburn	Vishy Algo	"I have two models, `Jane` and `Bob`. `Jane` has ForeignKey relationship to `Bob`.

I generate a migration 0001_initial:

{{{#!python
class Migration(migrations.Migration):
    operations = [
        migrations.CreateModel(
            name='Bob',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
            ],
        ),
        migrations.CreateModel(
            name='Jane',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('bob', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='constraintbug.bob')),
            ],
        ),
    ]
}}}

`Jane` is rendered in postgres as:

{{{#!sql
% docker compose exec db psql -U constraintbug
psql (18.0 (Debian 18.0-1.pgdg13+3))
Type ""help"" for help.

constraintbug=# \d constraintbug_jane
                     Table ""public.constraintbug_jane""
 Column |  Type  | Collation | Nullable |             Default              
--------+--------+-----------+----------+----------------------------------
 id     | bigint |           | not null | generated by default as identity
 bob_id | bigint |           | not null | 
Indexes:
    ""constraintbug_jane_pkey"" PRIMARY KEY, btree (id)
    ""constraintbug_jane_bob_id_35b76f6b"" btree (bob_id)
Foreign-key constraints:
    ""constraintbug_jane_bob_id_35b76f6b_fk_constraintbug_bob_id"" FOREIGN KEY (bob_id) REFERENCES constraintbug_bob(id) DEFERRABLE INITIALLY DEFERRED
}}}

Note the FK constraint.

Now, I decide to manually write a migration, because I want to remove `Bob` and replace it with a new thing. In my case, I was introducing model inheritance, and didn't want to revise my code to remove everything, `makemigrations`, add everything back,  `makemigrations` again, and I decided to just manually type `migrations.DeleteModel()`.

{{{#!python
class Migration(migrations.Migration):
    operations = [
        migrations.DeleteModel(  # this should fail?
            name='Bob',
        ),
    ]
}}}

Now things start to go wrong. I would expect at this point that the migration should fail, because I'm trying to delete a table that is referred to by the FK constraint. Instead, is just deletes the constraint:

{{{#!sql
constraintbug=# \d constraintbug_jane
                     Table ""public.constraintbug_jane""
 Column |  Type  | Collation | Nullable |             Default              
--------+--------+-----------+----------+----------------------------------
 id     | bigint |           | not null | generated by default as identity
 bob_id | bigint |           | not null | 
Indexes:
    ""constraintbug_jane_pkey"" PRIMARY KEY, btree (id)
    ""constraintbug_jane_bob_id_35b76f6b"" btree (bob_id)
}}}

I suppose we could say that this is an ""intermediate"" state, but then, I go and add the model back:

{{{#!python
class Migration(migrations.Migration):
    operations = [
        migrations.CreateModel(  # maybe this should re-create the FK constraint on jane?
            name='Bob',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
            ],
        ),
    ]
}}}

But `Jane` is still missing her constraint, and worse, I can do things like:
{{{#!python
Jane.objects.create(
    bob_id=1234,  # there is no such bob with pk 1234, this should fail!!!
)
}}}

Here's a wee example repo showing the issue:
https://github.com/daggaz/django-deletemodel/tree/master

I think that either:
* the `DeleteModel()` migration should fail to delete a model that is referenced
* the 2nd `CreateModel()` migration should recreate the FK constraint on `Jane` that `DeleteModel()` deleted
* at the very least the docs should have very big warning
"	Bug	assigned	Migrations	6.0	Normal			Simon Charette	Accepted	1	0	0	1	0	0
