Django 6.1 added three on_delete policies that run in the database instead of in Python:
from django . db import models
class Attachment ( models . Model ) : order = models . ForeignKey ( "shop.Order" , on_delete = models . DB_CASCADE ) file = models . FileField ( )
Enter fullscreen mode
Exit fullscreen mode
DB_CASCADE , DB_SET_NULL and DB_SET_DEFAULT put ON DELETE CASCADE / SET NULL / SET DEFAULT on the foreign-key constraint and let the database do the work. Deleting an Order becomes one DELETE statement. Django no longer loads every child row into memory first to find out what else it has to delete.
That speed has a cost, and the 6.1 release notes say so: DB_CASCADE does not send pre_delete or post_delete for the rows the database removes. Django never sees those rows, so it has nothing to send signals about.
What stops working
Most projects have at least one delete handler they no longer think about:
from django . db . models . signals import post_delete from django .…