#35510: migration on_delete=django.db.models.deletion.CASCADE does not create a 
ON
DELETE CASCADE constraint
-------------------------------------+-------------------------------------
               Reporter:  Daniel     |          Owner:  nobody
  Ahern                              |
                   Type:  Bug        |         Status:  new
              Component:  Database   |        Version:  5.0
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 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')),
 }}}
-- 
Ticket URL: <https://code.djangoproject.com/ticket/35510>
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 django-updates+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/0107018ff83b9303-50b1cce2-d751-43d0-a2aa-7bfa320e9895-000000%40eu-central-1.amazonses.com.

Reply via email to