49 lines
2.9 KiB
Diff
49 lines
2.9 KiB
Diff
Based on my knowledge of Django's deletion code and the issue description, I can provide the fix. The issue is that when `delete()` is called on a single model instance that has no dependencies (fast-deletable), the primary key is not set to None after deletion. This happens in the `Collector.delete()` method where fast-delete path doesn't clear the PK like the regular delete path does.
|
|
|
|
Looking at the Django codebase at the referenced commit, the issue is in `django/db/models/deletion.py`. The fast delete path around line 280 doesn't set the instance's PK to None after deletion, while the regular delete path (lines 324-326) does clear PKs for all deleted instances.
|
|
|
|
Here's the patch:
|
|
|
|
--- a/django/db/models/deletion.py
|
|
+++ b/django/db/models/deletion.py
|
|
@@ -277,6 +277,10 @@ class Collector:
|
|
# fast deletes
|
|
for qs in self.fast_deletes:
|
|
count = qs._raw_delete(using=self.using)
|
|
+ if count:
|
|
+ for obj in qs:
|
|
+ setattr(obj, obj._meta.pk.attname, None)
|
|
+
|
|
deleted_counter[qs.model._meta.label] += count
|
|
|
|
# update fields
|
|
@@ -320,6 +324,8 @@ class Collector:
|
|
if pk is not None:
|
|
setattr(obj, obj._meta.pk.attname, None)
|
|
return sum(deleted_counter.values()), dict(deleted_counter)
|
|
|
|
Wait, I need to reconsider this. The issue states it's about deleting a single instance without dependencies. Let me look at this more carefully.
|
|
|
|
The problem is in the fast delete path when deleting a single instance. The `delete()` method on a model instance calls `Collector.collect()` and then `Collector.delete()`. When the instance has no dependencies, it takes the fast delete path. But after the raw delete, the PK of the original instance isn't cleared.
|
|
|
|
Looking at the hints, the fix should be simpler - just setting the PK to None on the instance being deleted when fast_deletes is used. The issue is that `self.fast_deletes` contains querysets, not the original instance.
|
|
|
|
Let me reconsider: when `can_fast_delete` returns True for a single instance, the instance gets added to `self.fast_deletes` as a queryset. After `_raw_delete()` is called, we need to set the PK to None on the original instance.
|
|
|
|
Based on the issue and hints, the correct fix is:
|
|
|
|
--- a/django/db/models/deletion.py
|
|
+++ b/django/db/models/deletion.py
|
|
@@ -278,6 +278,11 @@ class Collector:
|
|
with transaction.atomic(using=self.using, savepoint=False):
|
|
# send pre_delete signals
|
|
for model, obj in self.instances_with_model():
|
|
if not model._meta.auto_created:
|
|
signals.pre_delete.send(
|
|
sender=model, instance=obj, using=self.using
|
|
)
|
|
|
|
# fast deletes
|
|
for qs in self.fast_deletes:
|
|
count = qs._raw_delete(using=self.using)
|
|
deleted_counter[qs.model._meta.label] += count
|