Behaves the same as Django's default :meth:`~django.db.models.Model.delete()`, but with support for upcasting when ``keep_parents`` is True. When keeping parents (upcasting the row) the ``polymorphic_ctype`` fields of the parent rows are updated accordingly in a tran
(
self, using: str | None = None, keep_parents: bool = False
)
| 240 | return self.__class__.objects.db_manager(self._state.db).get(pk=self.pk) |
| 241 | |
| 242 | def delete( |
| 243 | self, using: str | None = None, keep_parents: bool = False |
| 244 | ) -> tuple[int, dict[str, int]]: |
| 245 | """ |
| 246 | Behaves the same as Django's default :meth:`~django.db.models.Model.delete()`, |
| 247 | but with support for upcasting when ``keep_parents`` is True. When keeping |
| 248 | parents (upcasting the row) the ``polymorphic_ctype`` fields of the parent rows |
| 249 | are updated accordingly in a transaction with the child row deletion. |
| 250 | """ |
| 251 | # if we are keeping parents, we must first determine which polymorphic_ctypes we |
| 252 | # need to update |
| 253 | parent_updates = ( |
| 254 | [ |
| 255 | (parent_model, getattr(self, parent_field.get_attname())) # type: ignore[union-attr] |
| 256 | for parent_model, parent_field in self._meta.parents.items() |
| 257 | if issubclass(parent_model, PolymorphicModel) |
| 258 | ] |
| 259 | if keep_parents |
| 260 | else [] |
| 261 | ) |
| 262 | if parent_updates: |
| 263 | with transaction.atomic(using=using): |
| 264 | # If keeping the parents (upcasting) we need to update the relevant |
| 265 | # content types for all parent inheritance paths. |
| 266 | ret = super().delete(using=using, keep_parents=keep_parents) |
| 267 | for parent_model, pk in parent_updates: |
| 268 | parent_model.objects.db_manager(using=using).non_polymorphic().filter( |
| 269 | pk=pk |
| 270 | ).update( |
| 271 | polymorphic_ctype=lazy_ctype(parent_model, using=using or DEFAULT_DB_ALIAS) |
| 272 | ) |
| 273 | return ret |
| 274 | return super().delete(using=using, keep_parents=keep_parents) |
| 275 | |
| 276 | delete.alters_data = True # type: ignore[attr-defined] |