Skip to content

Commit 44f687e

Browse files
committed
Base manager can now be used for clean_duplicate_history
1 parent 309609e commit 44f687e

File tree

4 files changed

+88
-3
lines changed

4 files changed

+88
-3
lines changed

docs/utils.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ from the duplicate check
3131
3232
$ python manage.py clean_duplicate_history --auto --excluded_fields field1 field2
3333
34+
You can use Django's base manager to perform the cleanup over all records,
35+
including those that would otherwise be filtered or modified by a
36+
custom manager, by using the ``--base-manager`` flag.
37+
38+
.. code-block:: bash
39+
40+
$ python manage.py clean_duplicate_history --auto --base-manager
41+
3442
clean_old_history
3543
-----------------------
3644

simple_history/management/commands/clean_duplicate_history.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
from django.db import transaction
22
from django.utils import timezone
33

4-
from ... import models, utils
5-
from ...exceptions import NotHistoricalModelError
4+
from ... import utils
65
from . import populate_history
76

87

@@ -36,10 +35,19 @@ def add_arguments(self, parser):
3635
nargs="+",
3736
help="List of fields to be excluded from the diff_against check",
3837
)
38+
parser.add_argument(
39+
"--base-manager",
40+
action="store_true",
41+
default=False,
42+
help="Use Django's base manager to handle all records stored in the database,"
43+
" including those that would otherwise be filtered or modified by a"
44+
" custom manager.",
45+
)
3946

4047
def handle(self, *args, **options):
4148
self.verbosity = options["verbosity"]
4249
self.excluded_fields = options.get("excluded_fields")
50+
self.base_manager = options.get("base_manager")
4351

4452
to_process = set()
4553
model_strings = options.get("models", []) or args
@@ -72,7 +80,10 @@ def _process(self, to_process, date_back=None, dry_run=True):
7280
continue
7381

7482
# Break apart the query so we can add additional filtering
75-
model_query = model.objects.all()
83+
if self.base_manager:
84+
model_query = model._base_manager.all()
85+
else:
86+
model_query = model._default_manager.all()
7687

7788
# If we're provided a stop date take the initial hit of getting the
7889
# filtered records to iterate over

simple_history/tests/models.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,22 @@ class PollWithAlternativeManager(models.Model):
9292
history = HistoricalRecords()
9393

9494

95+
class CustomPollManager(models.Manager):
96+
def get_queryset(self):
97+
return super(CustomPollManager, self).get_queryset().exclude(hidden=True)
98+
99+
100+
class PollWithCustomManager(models.Model):
101+
some_objects = CustomPollManager()
102+
all_objects = models.Manager()
103+
104+
question = models.CharField(max_length=200)
105+
pub_date = models.DateTimeField("date published")
106+
hidden = models.BooleanField(default=False)
107+
108+
history = HistoricalRecords()
109+
110+
95111
class IPAddressHistoricalModel(models.Model):
96112
ip_address = models.GenericIPAddressField()
97113

simple_history/tests/tests/test_commands.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
CustomManagerNameModel,
1818
Place,
1919
Poll,
20+
PollWithCustomManager,
2021
PollWithExcludeFields,
2122
Restaurant,
2223
)
@@ -283,6 +284,55 @@ def test_auto_cleanup(self):
283284
)
284285
self.assertEqual(Poll.history.all().count(), 2)
285286

287+
def _prepare_cleanup_manager(self):
288+
one = PollWithCustomManager._default_manager.create(
289+
question="This is hidden in default manager",
290+
pub_date=datetime.now(),
291+
hidden=True,
292+
)
293+
one.save()
294+
295+
two = PollWithCustomManager._default_manager.create(
296+
question="This is visible in default manager", pub_date=datetime.now()
297+
)
298+
two.save()
299+
300+
self.assertEqual(PollWithCustomManager.history.count(), 4)
301+
302+
def test_auto_cleanup_defaultmanager(self):
303+
self._prepare_cleanup_manager()
304+
305+
out = StringIO()
306+
management.call_command(
307+
self.command_name, auto=True, stdout=out, stderr=StringIO()
308+
)
309+
self.assertEqual(
310+
out.getvalue(),
311+
"Removed 1 historical records for "
312+
"<class 'simple_history.tests.models.PollWithCustomManager'>\n",
313+
)
314+
self.assertEqual(PollWithCustomManager.history.count(), 3)
315+
316+
def test_auto_cleanup_basemanage(self):
317+
self._prepare_cleanup_manager()
318+
319+
out = StringIO()
320+
management.call_command(
321+
self.command_name,
322+
auto=True,
323+
base_manager=True,
324+
stdout=out,
325+
stderr=StringIO(),
326+
)
327+
self.assertEqual(
328+
out.getvalue(),
329+
"Removed 1 historical records for "
330+
"<class 'simple_history.tests.models.PollWithCustomManager'>\n"
331+
"Removed 1 historical records for "
332+
"<class 'simple_history.tests.models.PollWithCustomManager'>\n",
333+
)
334+
self.assertEqual(PollWithCustomManager.history.count(), 2)
335+
286336
def test_auto_cleanup_verbose(self):
287337
p = Poll.objects.create(
288338
question="Will this be deleted?", pub_date=datetime.now()

0 commit comments

Comments
 (0)