﻿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
36428	Collector.delete() calls sort() but does not order deletions correctly when nullable FK is present with non-null value	Andréas Kühne		"When using DeleteView or Model.delete() in Django 5.1.8, I encountered a IntegrityError from PostgreSQL. The issue stems from the deletion order of models: Django attempts to delete a parent (ActivityLocation) before its dependent child (BookableItem), despite on_delete=models.CASCADE being set.

This occurs even though the Collector calls .sort(), which is supposed to reorder models in dependency-safe order. The BookableItem.location FK is nullable (null=True), but the actual instance has a non-null FK set.

Models to reproduce:

{{{
from django.db import models

class ActivityLocation(models.Model):
    name = models.CharField(max_length=100)

class BookableItem(models.Model):
    name = models.CharField(max_length=100)
    location = models.ForeignKey(
        ActivityLocation,
        on_delete=models.CASCADE,
        related_name='bookable_items',
        null=True,
        blank=True,
    )

}}}

Steps to reproduce:

{{{
# Create parent and child
location = ActivityLocation.objects.create(name=""Test Location"")
item = BookableItem.objects.create(name=""Test Item"", location=location)

# Try to delete the location
location.delete() 
}}}

What I think should happen:
BookableItem should be deleted before ActivityLocation, as Django is responsible for enforcing deletion order (Postgres won’t do it automatically with deferred constraints).

What actually happens:
Django runs Collector.delete() which internally calls sort(), but the model deletion order remains:

{{{
[ActivityLocation, BookableItem]
}}}

If I however change to this:


{{{
from django.db import models

class BookableItem(models.Model):
    name = models.CharField(max_length=100)
    location = models.ForeignKey(
        ActivityLocation,
        on_delete=models.CASCADE,
        related_name='bookable_items',
    )
}}}

Then the code works as expected."	Bug	closed	Database layer (models, ORM)	5.1	Normal	invalid		Andréas Kühne	Unreviewed	0	0	0	0	0	0
