#36779: DeleteModel can lead to missing FK constraints
--------------------------------+--------------------------------------
Reporter: Jamie Cockburn | Type: Bug
Status: new | Component: Migrations
Version: 6.0 | Severity: Normal
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
--------------------------------+--------------------------------------
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
--
Ticket URL: <https://code.djangoproject.com/ticket/36779>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/django-updates/0107019af438b6e1-573acdc1-a8b2-4bf0-b433-974da2ac1869-000000%40eu-central-1.amazonses.com.