From d4f99c272963766e4accc2e747bb99c1e6641bc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ho=C3=A0ng=20Qu=E1=BB=91c=20H=C6=B0ng?= <40592382+hoangquochung1110@users.noreply.github.com> Date: Mon, 4 Nov 2024 20:39:25 +0700 Subject: [PATCH] Add AUDITLOG_TRUNCATE_CHANGES_DISPLAY and AUDITLOG_TRUNCATE_LIMIT (#684) * Add AUDITLOG_TRUNCATE_CHANGES_DISPLAY and AUDITLOG_TRUNCATE_LIMIT To configure how many characters will be truncated or disable it * Add AUDITLOG_CHANGE_DISPLAY_TRUNCATE_LENGTH settings to keep or truncate strings of `changes_display_dict` property at a variable length --- CHANGELOG.md | 1 + auditlog/conf.py | 5 +++++ auditlog/models.py | 6 +++--- auditlog_tests/tests.py | 31 +++++++++++++++++++++++++++++++ docs/source/usage.rst | 10 ++++++++++ 5 files changed, 50 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2f3b43..ebd95d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - feat: Added `LogEntry.remote_port` field. ([#671](https://github.com/jazzband/django-auditlog/pull/671)) - feat: Added `truncate` option to `auditlogflush` management command. ([#681](https://github.com/jazzband/django-auditlog/pull/681)) +- feat: Added `AUDITLOG_CHANGE_DISPLAY_TRUNCATE_LENGTH` settings to keep or truncate strings of `changes_display_dict` property at variable length. ([#684](https://github.com/jazzband/django-auditlog/pull/684)) - Drop Python 3.8 support. ([#678](https://github.com/jazzband/django-auditlog/pull/678)) - Confirm Django 5.1 support and drop Django 3.2 support. ([#677](https://github.com/jazzband/django-auditlog/pull/677)) diff --git a/auditlog/conf.py b/auditlog/conf.py index dbdfc5b..fe347cc 100644 --- a/auditlog/conf.py +++ b/auditlog/conf.py @@ -45,3 +45,8 @@ settings.AUDITLOG_USE_TEXT_CHANGES_IF_JSON_IS_NOT_PRESENT = getattr( settings.AUDITLOG_DISABLE_REMOTE_ADDR = getattr( settings, "AUDITLOG_DISABLE_REMOTE_ADDR", False ) + +# Number of characters at which changes_display_dict property should be shown +settings.AUDITLOG_CHANGE_DISPLAY_TRUNCATE_LENGTH = getattr( + settings, "AUDITLOG_CHANGE_DISPLAY_TRUNCATE_LENGTH", 140 +) diff --git a/auditlog/models.py b/auditlog/models.py index 3d10633..49e7aba 100644 --- a/auditlog/models.py +++ b/auditlog/models.py @@ -506,9 +506,9 @@ class LogEntry(models.Model): 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]}..." + truncate_at = settings.AUDITLOG_CHANGE_DISPLAY_TRUNCATE_LENGTH + if 0 <= truncate_at < len(value): + value = value[:truncate_at] + ("..." if truncate_at > 0 else "") values_display.append(value) diff --git a/auditlog_tests/tests.py b/auditlog_tests/tests.py index 8f8b825..d94db9f 100644 --- a/auditlog_tests/tests.py +++ b/auditlog_tests/tests.py @@ -1561,6 +1561,37 @@ class CharFieldTextFieldModelTest(TestCase): msg="The field should display the entire string because it is less than 140 characters", ) + def test_changes_display_dict_longtextfield_to_be_truncated_at_custom_length(self): + with override_settings(AUDITLOG_CHANGE_DISPLAY_TRUNCATE_LENGTH=10): + length = settings.AUDITLOG_CHANGE_DISPLAY_TRUNCATE_LENGTH + self.assertEqual( + self.obj.history.latest().changes_display_dict["longtextfield"][1], + f"{self.PLACEHOLDER_LONGCHAR[:length]}...", + msg=f"The string should be truncated at {length} characters with an ellipsis at the end.", + ) + + def test_changes_display_dict_longtextfield_to_be_truncated_to_empty_string(self): + with override_settings(AUDITLOG_CHANGE_DISPLAY_TRUNCATE_LENGTH=0): + length = settings.AUDITLOG_CHANGE_DISPLAY_TRUNCATE_LENGTH + self.assertEqual( + self.obj.history.latest().changes_display_dict["longtextfield"][1], + "", + msg=f"The string should be empty as AUDITLOG_TRUNCATE_CHANGES_DISPLAY is set to {length}.", + ) + + def test_changes_display_dict_longtextfield_with_truncation_disabled(self): + with override_settings(AUDITLOG_CHANGE_DISPLAY_TRUNCATE_LENGTH=-1): + length = settings.AUDITLOG_CHANGE_DISPLAY_TRUNCATE_LENGTH + 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 {length} characters" + "as AUDITLOG_TRUNCATE_CHANGES_DISPLAY is set to a negative number" + ), + ) + class PostgresArrayFieldModelTest(TestCase): databases = "__all__" diff --git a/docs/source/usage.rst b/docs/source/usage.rst index 843c189..0c79a56 100644 --- a/docs/source/usage.rst +++ b/docs/source/usage.rst @@ -305,6 +305,16 @@ If the value is `None`, the default getter will be used. .. versionadded:: 3.0.0 +**AUDITLOG_CHANGE_DISPLAY_TRUNCATE_LENGTH** + +This configuration variable defines the truncation behavior for strings in `changes_display_dict`, with a default value of `140` characters. + +0: The entire string is truncated, resulting in an empty output. +Positive values (e.g., 5): Truncates the string, keeping only the specified number of characters followed by an ellipsis (...) after the limit. +Negative values: No truncation occurs, and the full string is displayed. + +.. versionadded:: 3.1.0 + Actors ------