From 68a4c14c7474ecca72c9033a5380893c5e3fe843 Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Tue, 16 Apr 2024 02:51:07 +0200 Subject: [PATCH 1/3] Auto-generate manager implementation for `CustomSoftDelete` Besides requiring less code, this also allows the django-stubs mypy plugin to automatically generate a type-annotated version of the manager. Unfortunately, the plugin does not put a `ClassVar` annotation on `objects`, which is why we need the suppression. --- tests/managers.py | 9 +-------- tests/models.py | 11 ++++++++--- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/tests/managers.py b/tests/managers.py index 03ea473..640420c 100644 --- a/tests/managers.py +++ b/tests/managers.py @@ -1,13 +1,6 @@ -from model_utils.managers import SoftDeletableManager, SoftDeletableQuerySet +from model_utils.managers import SoftDeletableQuerySet class CustomSoftDeleteQuerySet(SoftDeletableQuerySet): def only_read(self): return self.filter(is_read=True) - - -class CustomSoftDeleteManager(SoftDeletableManager): - _queryset_class = CustomSoftDeleteQuerySet - - def only_read(self): - return self.get_queryset().only_read() diff --git a/tests/models.py b/tests/models.py index 44f7590..b5b4f37 100644 --- a/tests/models.py +++ b/tests/models.py @@ -9,7 +9,12 @@ from django.utils.translation import gettext_lazy as _ from model_utils import Choices from model_utils.fields import MonitorField, SplitField, StatusField, UUIDField -from model_utils.managers import InheritanceManager, JoinManager, QueryManager +from model_utils.managers import ( + InheritanceManager, + JoinManager, + QueryManager, + SoftDeletableManager, +) from model_utils.models import ( SoftDeletableModel, StatusModel, @@ -19,7 +24,7 @@ from model_utils.models import ( ) from model_utils.tracker import FieldTracker, ModelTracker from tests.fields import MutableField -from tests.managers import CustomSoftDeleteManager +from tests.managers import CustomSoftDeleteQuerySet class InheritanceManagerTestRelated(models.Model): @@ -350,7 +355,7 @@ class SoftDeletable(SoftDeletableModel): class CustomSoftDelete(SoftDeletableModel): is_read = models.BooleanField(default=False) - objects: ClassVar[CustomSoftDeleteManager[SoftDeletableModel]] = CustomSoftDeleteManager() + objects = SoftDeletableManager.from_queryset(CustomSoftDeleteQuerySet)() # type: ignore[misc] class StringyDescriptor: From 800961626a3c7a6c8d477af8b98f4f41435a05b7 Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Tue, 16 Apr 2024 03:14:11 +0200 Subject: [PATCH 2/3] Move `CustomSoftDeleteQuerySet` to `tests.models` The `CustomSoftDeleteQuerySet` class was the only code left in the `test.managers` module, while it is not in fact a `Manager`. --- tests/managers.py | 6 ------ tests/models.py | 7 ++++++- 2 files changed, 6 insertions(+), 7 deletions(-) delete mode 100644 tests/managers.py diff --git a/tests/managers.py b/tests/managers.py deleted file mode 100644 index 640420c..0000000 --- a/tests/managers.py +++ /dev/null @@ -1,6 +0,0 @@ -from model_utils.managers import SoftDeletableQuerySet - - -class CustomSoftDeleteQuerySet(SoftDeletableQuerySet): - def only_read(self): - return self.filter(is_read=True) diff --git a/tests/models.py b/tests/models.py index b5b4f37..442200f 100644 --- a/tests/models.py +++ b/tests/models.py @@ -14,6 +14,7 @@ from model_utils.managers import ( JoinManager, QueryManager, SoftDeletableManager, + SoftDeletableQuerySet, ) from model_utils.models import ( SoftDeletableModel, @@ -24,7 +25,6 @@ from model_utils.models import ( ) from model_utils.tracker import FieldTracker, ModelTracker from tests.fields import MutableField -from tests.managers import CustomSoftDeleteQuerySet class InheritanceManagerTestRelated(models.Model): @@ -352,6 +352,11 @@ class SoftDeletable(SoftDeletableModel): all_objects: ClassVar[Manager[SoftDeletable]] = models.Manager() +class CustomSoftDeleteQuerySet(SoftDeletableQuerySet): + def only_read(self): + return self.filter(is_read=True) + + class CustomSoftDelete(SoftDeletableModel): is_read = models.BooleanField(default=False) From 512d0f189015b3a0d28725bc72428a8e8b8967bb Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Tue, 16 Apr 2024 03:59:50 +0200 Subject: [PATCH 3/3] Avoid deprecated `SoftDeletableModel.objects` manager in tests Use the `available_objects` manager instead. --- tests/models.py | 2 +- tests/test_managers/test_softdelete_manager.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/models.py b/tests/models.py index 442200f..ac65931 100644 --- a/tests/models.py +++ b/tests/models.py @@ -360,7 +360,7 @@ class CustomSoftDeleteQuerySet(SoftDeletableQuerySet): class CustomSoftDelete(SoftDeletableModel): is_read = models.BooleanField(default=False) - objects = SoftDeletableManager.from_queryset(CustomSoftDeleteQuerySet)() # type: ignore[misc] + available_objects = SoftDeletableManager.from_queryset(CustomSoftDeleteQuerySet)() # type: ignore[misc] class StringyDescriptor: diff --git a/tests/test_managers/test_softdelete_manager.py b/tests/test_managers/test_softdelete_manager.py index db495c4..aec5357 100644 --- a/tests/test_managers/test_softdelete_manager.py +++ b/tests/test_managers/test_softdelete_manager.py @@ -6,21 +6,21 @@ from tests.models import CustomSoftDelete class CustomSoftDeleteManagerTests(TestCase): def test_custom_manager_empty(self): - qs = CustomSoftDelete.objects.only_read() + qs = CustomSoftDelete.available_objects.only_read() self.assertEqual(qs.count(), 0) def test_custom_qs_empty(self): - qs = CustomSoftDelete.objects.all().only_read() + qs = CustomSoftDelete.available_objects.all().only_read() self.assertEqual(qs.count(), 0) def test_is_read(self): for is_read in [True, False, True, False]: - CustomSoftDelete.objects.create(is_read=is_read) - qs = CustomSoftDelete.objects.only_read() + CustomSoftDelete.available_objects.create(is_read=is_read) + qs = CustomSoftDelete.available_objects.only_read() self.assertEqual(qs.count(), 2) def test_is_read_removed(self): for is_read, is_removed in [(True, True), (True, False), (False, False), (False, True)]: - CustomSoftDelete.objects.create(is_read=is_read, is_removed=is_removed) - qs = CustomSoftDelete.objects.only_read() + CustomSoftDelete.available_objects.create(is_read=is_read, is_removed=is_removed) + qs = CustomSoftDelete.available_objects.only_read() self.assertEqual(qs.count(), 1)