Django's .delete() functionality doesn't work when a polymorphic model subclass is referenced by an instance of the base class using a self referential foreign key. See below for model definitions and code to reproduce issue.
# myapp/models.py
from django.db import models
from polymorphic.models import PolymorphicModel
class A(PolymorphicModel):
self_referential = models.ForeignKey("self", null=True, blank=True, on_delete=models.CASCADE)
class B(A):
name = models.CharField(max_length=256)
### script.py
from myapp.models import A, B
b = B.objects.create(self_referential=None, name="b")
a = A.objects.create(self_referential=b)
print(hasattr(a, "a_ptr"))
print(hasattr(b, "a_ptr"))
A.objects.all().delete()
Running the above results in the following output:
False
True
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
File /script.py:29
26 print(hasattr(a, "a_ptr"))
27 print(hasattr(b, "a_ptr"))
---> 29 A.objects.all().delete()
31 # %%
File /.venv/lib/python3.10/site-packages/django/db/models/query.py:745, in QuerySet.delete(self)
742 del_query.query.clear_ordering(force_empty=True)
744 collector = Collector(using=del_query.db)
--> 745 collector.collect(del_query)
746 deleted, _rows_count = collector.delete()
748 # Clear the result cache, in case this QuerySet gets reused.
File /.venv/lib/python3.10/site-packages/django/db/models/deletion.py:256, in Collector.collect(self, objs, source, nullable, collect_related, source_attr, reverse_dependency, keep_parents, fail_on_restricted)
254 for ptr in concrete_model._meta.parents.values():
255 if ptr:
--> 256 parent_objs = [getattr(obj, ptr.name) for obj in new_objs]
257 self.collect(parent_objs, source=model,
258 source_attr=ptr.remote_field.related_name,
259 collect_related=False,
260 reverse_dependency=True,
261 fail_on_restricted=False)
262 if not collect_related:
File /.venv/lib/python3.10/site-packages/django/db/models/deletion.py:256, in <listcomp>(.0)
254 for ptr in concrete_model._meta.parents.values():
255 if ptr:
--> 256 parent_objs = [getattr(obj, ptr.name) for obj in new_objs]
257 self.collect(parent_objs, source=model,
258 source_attr=ptr.remote_field.related_name,
259 collect_related=False,
260 reverse_dependency=True,
261 fail_on_restricted=False)
262 if not collect_related:
AttributeError: 'A' object has no attribute 'a_ptr'
Django's
.delete()
functionality doesn't work when a polymorphic model subclass is referenced by an instance of the base class using a self referential foreign key. See below for model definitions and code to reproduce issue.Running the above results in the following output:
Package versions