Django on_delete=models.CASCADE has no effect at SQL level

Rakib picture Rakib · Mar 3, 2016 · Viewed 7.2k times · Source

My models.py file contains:

class User(models.Model):
    email = models.CharField(max_length=100, unique=True)
    password = models.CharField(max_length=100)
    create_time = models.DateTimeField(auto_now_add=True)

class Session(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    token = models.CharField(max_length=100, unique=True)

When i command python manage.py makemigrations and then command python manage.py sqlmigrate <app_name> <migration_name> i don't see anything that says "ON DELETE=CASCADE"

However, the migrations work without failure when i type python manage.py migrate.

Now, if i go to the mysql table (using SequelPro) and try to delete a row for a user who currently has a session entry, i get the following error: "One row was not removed. Reload the table to be sure that the contents have not changed in the meantime. Check the Console for possible errors inside the primary key(s) of this table!".

Now, when i go to the session table and delete the sessions of this user and then try to delete the user's row from the user table, it deletes properly. This indicates ON DELETE = CASCADE is not actually working at the MySQL level.

How can i correct it?

Answer

knbk picture knbk · Mar 3, 2016

From the docs (emphasis mine):

ForeignKey.on_delete

When an object referenced by a ForeignKey is deleted, Django will emulate the behavior of the SQL constraint specified by the on_delete argument.

Django does not actually set an ON DELETE clause in the database. If you need one, you can add one manually using a RunSQL operation. Be sure to use the same index name, or keep the original index, or you might run into errors later on.