From 8f20ca3111e40086c377f902f6171db831638d8b Mon Sep 17 00:00:00 2001 From: Yurchenko Sergey Date: Mon, 27 Jan 2020 22:24:32 +0300 Subject: [PATCH] command-to-delete-stale-records (#355) * command-to-delete-stale-records --- constance/management/commands/constance.py | 31 ++++++++++++++++++++++ docs/index.rst | 7 +++++ tests/test_cli.py | 11 ++++++++ 3 files changed, 49 insertions(+) diff --git a/constance/management/commands/constance.py b/constance/management/commands/constance.py index 4d78769..c78ebf6 100644 --- a/constance/management/commands/constance.py +++ b/constance/management/commands/constance.py @@ -1,3 +1,5 @@ +from django.apps import apps +from django.conf import settings from django.core.exceptions import ValidationError from django.core.management import BaseCommand, CommandError from django.utils.translation import ugettext as _ @@ -40,6 +42,13 @@ class Command(BaseCommand): # use nargs='+' so that we pass a list to MultiValueField (eg SplitDateTimeField) parser_set.add_argument('value', help='value to set', metavar='VALUE', nargs='+') + self._subparsers_add_parser( + subparsers, + 'remove_stale_keys', + cmd=self, + help='delete all Constance keys and their values if they are not in settings.CONSTANCE_CONFIG (stale keys)', + ) + def _subparsers_add_parser(self, subparsers, name, **kwargs): # API in Django >= 2.1 changed and removed cmd parameter from add_parser @@ -71,3 +80,25 @@ class Command(BaseCommand): elif command == 'list': for k, v in get_values().items(): self.stdout.write("{}\t{}".format(k, v), ending="\n") + + elif command == 'remove_stale_keys': + try: + Constance = apps.get_model('database.Constance') + except LookupError: + Constance = None + + if Constance: + actual_keys = settings.CONSTANCE_CONFIG.keys() + + stale_records = Constance.objects.exclude(key__in=actual_keys) + if stale_records: + self.stdout.write("The following record will be deleted:", ending="\n") + else: + self.stdout.write("There are no stale records in database.", ending="\n") + + for stale_record in stale_records: + self.stdout.write("{}\t{}".format(stale_record.key, stale_record.value), ending="\n") + + stale_records.delete() + else: + self.stdout.write("Database backend is not set. Nothing is deleted", ending="\n") diff --git a/docs/index.rst b/docs/index.rst index 818f24b..b14340d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -326,6 +326,13 @@ This doesn't work:: ./manage.py constance set DATETIME_VALUE '2011-09-24 12:30:25' CommandError: Enter a list of values. + +remove_stale_keys - delete all stale records in database:: + + $ ./manage.py constance remove_stale_keys + +Record is considered stale if it exists in database but absent in config + Editing ------- diff --git a/tests/test_cli.py b/tests/test_cli.py index ec00239..1a17187 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,6 +1,7 @@ from datetime import datetime from textwrap import dedent +from django.apps import apps from django.conf import settings from django.core.management import call_command, CommandError from django.test import TransactionTestCase @@ -71,3 +72,13 @@ class CliTestCase(TransactionTestCase): def test_set_invalid_multi_value(self): self.assertRaisesMessage(CommandError, "Enter a list of values.", call_command, 'constance', 'set', 'DATETIME_VALUE', '2011-09-24 12:30:25') + + def test_delete_stale_records(self): + Constance = apps.get_model('database.Constance') + + initial_count = Constance.objects.count() + + Constance.objects.create(key='STALE_KEY', value=None) + call_command('constance', 'remove_stale_keys', stdout=self.out) + + self.assertEqual(Constance.objects.count(), initial_count)