diff --git a/auditlog/conf.py b/auditlog/conf.py index dbdfc5b4..7cc29f36 100644 --- a/auditlog/conf.py +++ b/auditlog/conf.py @@ -45,3 +45,11 @@ settings.AUDITLOG_DISABLE_REMOTE_ADDR = getattr( settings, "AUDITLOG_DISABLE_REMOTE_ADDR", False ) + +# Enable changes_display_dict truncator +settings.AUDITLOG_TRUNCATE_CHANGES_DISPLAY = getattr( + settings, "AUDITLOG_TRUNCATE_CHANGES_DISPLAY", True +) + +# Number of characters at which changes_display_dict property should be shown +settings.AUDITLOG_TRUNCATE_LIMIT = getattr(settings, "AUDITLOG_TRUNCATE_LIMIT", 140) diff --git a/auditlog/models.py b/auditlog/models.py index 3d106330..31154470 100644 --- a/auditlog/models.py +++ b/auditlog/models.py @@ -24,6 +24,7 @@ from django.utils.translation import gettext_lazy as _ from auditlog.diff import mask_str +from auditlog.text import truncatechars DEFAULT_OBJECT_REPR = "" @@ -506,9 +507,11 @@ def changes_display_dict(self): elif field_type in ["ForeignKey", "OneToOneField"]: value = self._get_changes_display_for_fk_field(field, value) - # check if length is longer than 140 and truncate with ellipsis - if len(value) > 140: - value = f"{value[:140]}..." + if ( + settings.AUDITLOG_TRUNCATE_CHANGES_DISPLAY + and len(value) > settings.AUDITLOG_TRUNCATE_LIMIT + ): + value = truncatechars(value, settings.AUDITLOG_TRUNCATE_LIMIT) values_display.append(value) diff --git a/auditlog/text.py b/auditlog/text.py new file mode 100644 index 00000000..57833b2a --- /dev/null +++ b/auditlog/text.py @@ -0,0 +1,11 @@ +class Truncator: + + def __init__(self, text) -> None: + self.text = text + + def chars(self, length: int) -> str: + return f"{self.text[:length]}..." + + +def truncatechars(text, length): + return Truncator(text).chars(length) diff --git a/auditlog_tests/test_settings.py b/auditlog_tests/test_settings.py index ba29ce77..0a8d0b67 100644 --- a/auditlog_tests/test_settings.py +++ b/auditlog_tests/test_settings.py @@ -26,15 +26,12 @@ "django.contrib.messages.middleware.MessageMiddleware", "auditlog.middleware.AuditlogMiddleware", ] - DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql", - "NAME": os.getenv( - "TEST_DB_NAME", "auditlog" + os.environ.get("TOX_PARALLEL_ENV", "") - ), - "USER": os.getenv("TEST_DB_USER", "postgres"), - "PASSWORD": os.getenv("TEST_DB_PASS", ""), + "NAME": "alana", + "USER": "alana", + "PASSWORD": os.getenv("TEST_DB_PASS", "django"), "HOST": os.getenv("TEST_DB_HOST", "127.0.0.1"), "PORT": os.getenv("TEST_DB_PORT", "5432"), } diff --git a/auditlog_tests/tests.py b/auditlog_tests/tests.py index 8f8b825f..9c52c028 100644 --- a/auditlog_tests/tests.py +++ b/auditlog_tests/tests.py @@ -1561,6 +1561,32 @@ def test_changes_display_dict_longtextfield(self): msg="The field should display the entire string because it is less than 140 characters", ) + def test_changes_display_dict_longtextfield_to_be_truncated_with_custom_limit(self): + with override_settings( + AUDITLOG_TRUNCATE_CHANGES_DISPLAY=True, + AUDITLOG_TRUNCATE_LIMIT=10, + ): + limit = settings.AUDITLOG_TRUNCATE_LIMIT + self.assertEqual( + self.obj.history.latest().changes_display_dict["longtextfield"][1], + f"{self.PLACEHOLDER_LONGCHAR[:limit]}...", + msg=f"The string should be truncated at {limit} characters with an ellipsis at the end.", + ) + + def test_changes_display_dict_longtextfield_with_truncation_disabled(self): + with override_settings(AUDITLOG_TRUNCATE_CHANGES_DISPLAY=False): + limit = settings.AUDITLOG_TRUNCATE_LIMIT + self.assertTrue(len(self.PLACEHOLDER_LONGTEXTFIELD) > limit) + self.assertEqual( + self.obj.history.latest().changes_display_dict["longtextfield"][1], + self.PLACEHOLDER_LONGTEXTFIELD, + msg=( + "The field should display the entire string " + f"even though it is longer than {limit} characters" + "as AUDITLOG_TRUNCATE_CHANGES_DISPLAY is set to False" + ), + ) + class PostgresArrayFieldModelTest(TestCase): databases = "__all__" diff --git a/docs/source/usage.rst b/docs/source/usage.rst index 843c189d..539a271c 100644 --- a/docs/source/usage.rst +++ b/docs/source/usage.rst @@ -305,6 +305,14 @@ If the value is `None`, the default getter will be used. .. versionadded:: 3.0.0 +**AUDITLOG_TRUNCATE_CHANGES_DISPLAY** + +You can use this settings to truncate characters in `changes_display_dict` property, True by default + +**AUDITLOG_TRUNCATE_LIMIT** + +Number of characters at which `changes_display_dict` property should be truncated + Actors ------