﻿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
35510	migration on_delete=django.db.models.deletion.CASCADE does not create a ON DELETE CASCADE constraint	Daniel Ahern	nobody	"Python 3.12.0 (using a conda environment)
Django 5.6
MariaDB/MySQL 8.0.30-0ubuntu0.22.04.1 (Ubuntu)

models.py:

{{{
from django.db import models

# class TableBoolean(models.Model):
#     field1 = models.BooleanField(default=False)

#     class Meta:
#         db_table = 'test_boolean'

class Parent(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name
    class Meta:
        db_table = 'test_parent'

class Child(models.Model):
    parent = models.ForeignKey(Parent, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

    class Meta:
        db_table = 'test_child'
}}}

Then I do:

python manage.py makemigrations v506

which makes:

{{{
# Generated by Django 5.0.6 on 2024-06-08 14:09

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Parent',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=100)),
            ],
            options={
                'db_table': 'test_parent',
            },
        ),
        migrations.CreateModel(
            name='Child',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=100)),
                ('parent', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='v506.parent')),
            ],
            options={
                'db_table': 'test_child',
            },
        ),
    ]
}}}

Running the migration creates a table that does NOT cascade delete:

{{{
| test_child | CREATE TABLE `test_child` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `parent_id` bigint NOT NULL,
  PRIMARY KEY (`id`),
  KEY `test_child_parent_id_e1a9888d_fk_test_parent_id` (`parent_id`),
  CONSTRAINT `test_child_parent_id_e1a9888d_fk_test_parent_id` FOREIGN KEY (`parent_id`) REFERENCES `test_parent` (`id`)
)
}}}

Then I test by:
{{{
mysql> insert into test_parent(name) values ('test_parent');

mysql> insert into test_child (name, parent_id) values ('test_child', 1);

mysql> delete from test_parent where id = 1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`django506`.`test_child`, CONSTRAINT `test_child_parent_id_e1a9888d_fk_test_parent_id` FOREIGN KEY (`parent_id`) REFERENCES `test_parent` (`id`))


}}}

I am able to alter the table:

{{{
ALTER TABLE `test_child`
DROP FOREIGN KEY `test_child_parent_id_e1a9888d_fk_test_parent_id`;

ALTER TABLE `test_child`
ADD CONSTRAINT `test_child_parent_id_e1a9888d_fk_test_parent_id`
FOREIGN KEY (`parent_id`) REFERENCES `test_parent` (`id`) ON DELETE CASCADE;

mysql> show create table test_child;

test_child | CREATE TABLE `test_child` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `parent_id` bigint NOT NULL,
  PRIMARY KEY (`id`),
  KEY `test_child_parent_id_e1a9888d_fk_test_parent_id` (`parent_id`),
  CONSTRAINT `test_child_parent_id_e1a9888d_fk_test_parent_id` FOREIGN KEY (`parent_id`) REFERENCES `test_parent` (`id`) ON DELETE CASCADE

mysql> delete from test_parent where id = 1;
Query OK, 1 row affected (0.01 sec)

mysql> select count(*) from test_child;
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

}}}

I would expect ON DELETE CASCADE to be on the table made by the migration because the migration has ""on_delete=django.db.models.deletion.CASCADE"" on the line:
{{{
('parent', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='v506.parent')),
}}}
"	Bug	closed	Database layer (models, ORM)	5.0	Normal	invalid			Unreviewed	0	0	0	0	0	0
