From 1673feae7b52d2f970fc46b7a107add0284b05a5 Mon Sep 17 00:00:00 2001 From: Guilherme Martins Crocetti <24530683+gmcrocetti@users.noreply.github.com> Date: Thu, 6 Jun 2024 14:38:10 -0300 Subject: [PATCH] chore: Replicate Django's signature at SoftDelete queryset --- CHANGES.rst | 1 + model_utils/managers.py | 10 +++++----- tests/test_models/test_softdeletable_model.py | 10 ++++++++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index f10c32ab..f05354ba 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -16,6 +16,7 @@ To be released - Make `soft` argument to `SoftDeletableModel.delete()` keyword-only - `JoinManager` and `JoinManagerMixin` have been deprecated; please use ``JoinQueryset.as_manager()`` instead +- Change `SoftDeletableQuerySetMixin.delete` to replicate Django's API. 4.5.1 (2024-05-02) ------------------ diff --git a/model_utils/managers.py b/model_utils/managers.py index 899b9887..4cb1ffcd 100644 --- a/model_utils/managers.py +++ b/model_utils/managers.py @@ -363,17 +363,17 @@ class SoftDeletableQuerySetMixin(Generic[ModelT]): its ``is_removed`` field to True. """ - def delete(self) -> None: + def delete(self) -> tuple[int, dict[str, int]]: """ Soft delete objects from queryset (set their ``is_removed`` field to True) """ - cast(QuerySet[ModelT], self).update(is_removed=True) + model: type[ModelT] = self.model # type: ignore[attr-defined] + number_of_deleted_objects = cast(QuerySet[ModelT], self).update(is_removed=True) + return number_of_deleted_objects, {model._meta.label: number_of_deleted_objects} -# Note that our delete() method does not return anything, unlike Django's. -# https://github.com/jazzband/django-model-utils/issues/541 -class SoftDeletableQuerySet(SoftDeletableQuerySetMixin[ModelT], QuerySet[ModelT]): # type: ignore[misc] +class SoftDeletableQuerySet(SoftDeletableQuerySetMixin[ModelT], QuerySet[ModelT]): pass diff --git a/tests/test_models/test_softdeletable_model.py b/tests/test_models/test_softdeletable_model.py index 1f58f435..8f4e656c 100644 --- a/tests/test_models/test_softdeletable_model.py +++ b/tests/test_models/test_softdeletable_model.py @@ -53,3 +53,13 @@ def test_instance_purge_no_connection(self) -> None: def test_deprecation_warning(self) -> None: self.assertWarns(DeprecationWarning, SoftDeletable.objects.all) + + def test_delete_queryset_return(self) -> None: + SoftDeletable.available_objects.create(name='a') + SoftDeletable.available_objects.create(name='b') + + result = SoftDeletable.available_objects.filter(name="a").delete() + + assert result == ( + 1, {SoftDeletable._meta.label: 1} + )