mirror of
https://github.com/jazzband/django-auditlog.git
synced 2026-03-16 22:20:26 +00:00
Add new setting to control FK change representation (#779)
* add new setting to activate string repr * skip using foreign key to construct and display diff of foreign key fields * concise name and documentation update # Conflicts: # docs/source/usage.rst * add test for enabled setting * fix code block in docs * fix version * add warning to documentation
This commit is contained in:
parent
d02ed6b9e0
commit
eb9eefd76f
5 changed files with 69 additions and 1 deletions
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#### Improvements
|
||||
|
||||
- feat: Add `AUDITLOG_USE_FK_STRING_REPRESENTATION` setting that controls how foreign key changes are represented ([#779)](https://github.com/jazzband/django-auditlog/pull/779))
|
||||
- Add `AUDITLOG_USE_BASE_MANAGER` setting to override default manager use ([#766](https://github.com/jazzband/django-auditlog/pull/766))
|
||||
- Drop 'Python 3.9' support ([#773](https://github.com/jazzband/django-auditlog/pull/773))
|
||||
|
||||
|
|
|
|||
|
|
@ -71,3 +71,8 @@ settings.AUDITLOG_LOGENTRY_MODEL = getattr(
|
|||
settings.AUDITLOG_USE_BASE_MANAGER = getattr(
|
||||
settings, "AUDITLOG_USE_BASE_MANAGER", False
|
||||
)
|
||||
|
||||
# Use string representation of referenced object in foreign key changes instead of its primary key
|
||||
settings.AUDITLOG_USE_FK_STRING_REPRESENTATION = getattr(
|
||||
settings, "AUDITLOG_USE_FK_STRING_REPRESENTATION", False
|
||||
)
|
||||
|
|
|
|||
|
|
@ -106,7 +106,11 @@ def get_field_value(obj, field, use_json_for_changes=False):
|
|||
value = json.dumps(value, sort_keys=True, cls=field.encoder)
|
||||
except TypeError:
|
||||
pass
|
||||
elif (field.one_to_one or field.many_to_one) and hasattr(field, "rel_class"):
|
||||
elif (
|
||||
not settings.AUDITLOG_USE_FK_STRING_REPRESENTATION
|
||||
and (field.one_to_one or field.many_to_one)
|
||||
and hasattr(field, "rel_class")
|
||||
):
|
||||
value = smart_str(getattr(obj, field.get_attname()), strings_only=True)
|
||||
else:
|
||||
value = getattr(obj, field.name)
|
||||
|
|
|
|||
|
|
@ -2407,6 +2407,29 @@ class TestRelatedDiffs(TestCase):
|
|||
self.assertEqual(int(log_create.changes_dict["related"][1]), one_simple.id)
|
||||
self.assertEqual(int(log_update.changes_dict["related"][1]), two_simple.id)
|
||||
|
||||
@override_settings(AUDITLOG_USE_FK_STRING_REPRESENTATION=True)
|
||||
def test_string_representation_of_fk_changes(self):
|
||||
"""FK changes should be stored using string representation when setting is enabled"""
|
||||
|
||||
t1 = self.test_date
|
||||
with freezegun.freeze_time(t1):
|
||||
simple = SimpleModel.objects.create(text="Test Foo")
|
||||
two_simple = SimpleModel.objects.create(text="Test Bar")
|
||||
instance = RelatedModel.objects.create(one_to_one=simple, related=simple)
|
||||
|
||||
t2 = self.test_date + datetime.timedelta(days=20)
|
||||
with freezegun.freeze_time(t2):
|
||||
instance.one_to_one = two_simple
|
||||
instance.related = two_simple
|
||||
instance.save()
|
||||
|
||||
self.assertEqual(instance.history.all().count(), 2)
|
||||
log_update = instance.history.filter(timestamp=t2).first()
|
||||
self.assertEqual(log_update.changes_dict["related"][0], "Test Foo")
|
||||
self.assertEqual(log_update.changes_dict["related"][1], "Test Bar")
|
||||
self.assertEqual(log_update.changes_dict["one_to_one"][0], "Test Foo")
|
||||
self.assertEqual(log_update.changes_dict["one_to_one"][1], "Test Bar")
|
||||
|
||||
|
||||
class TestModelSerialization(TestCase):
|
||||
def setUp(self):
|
||||
|
|
|
|||
|
|
@ -444,6 +444,41 @@ of the default one.
|
|||
.. versionadded:: 3.5.0
|
||||
Custom LogEntry model configuration via ``AUDITLOG_LOGENTRY_MODEL``
|
||||
|
||||
**AUDITLOG_USE_FK_STRING_REPRESENTATION**
|
||||
|
||||
Determines how changes to foreign key fields are recorded in log entries.
|
||||
|
||||
When `True`, changes to foreign key fields are stored using the string representation of related objects.
|
||||
When `False` (default), the primary key of the related objects is stored instead.
|
||||
|
||||
Before version 2.2.0, foreign key changes were stored using the string representation of the related objects.
|
||||
Starting from version 2.2.0, the default behavior was updated to store the primary key of the related objects instead.
|
||||
|
||||
Before:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{ "foreign_key_field": ["foo", "bar"] }
|
||||
|
||||
|
||||
After:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{ "foreign_key_field": [1, 2] }
|
||||
|
||||
You can use this option to enable the legacy behavior.
|
||||
|
||||
.. warning::
|
||||
|
||||
This reintroduces a known issue https://github.com/jazzband/django-auditlog/issues/421
|
||||
Commission Error: Causes unnecessary LogEntries even though no update occurrs because the string representation in memory changed
|
||||
Omission Error: More common problem, a related object is updated to another object with the same string representation, no update is logged
|
||||
|
||||
Beware of these problem when enabling this setting.
|
||||
|
||||
.. versionadded:: 3.4.0
|
||||
|
||||
Actors
|
||||
------
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue