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
|
#### 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))
|
- 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))
|
- 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 = getattr(
|
||||||
settings, "AUDITLOG_USE_BASE_MANAGER", False
|
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)
|
value = json.dumps(value, sort_keys=True, cls=field.encoder)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
pass
|
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)
|
value = smart_str(getattr(obj, field.get_attname()), strings_only=True)
|
||||||
else:
|
else:
|
||||||
value = getattr(obj, field.name)
|
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_create.changes_dict["related"][1]), one_simple.id)
|
||||||
self.assertEqual(int(log_update.changes_dict["related"][1]), two_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):
|
class TestModelSerialization(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
|
||||||
|
|
@ -444,6 +444,41 @@ of the default one.
|
||||||
.. versionadded:: 3.5.0
|
.. versionadded:: 3.5.0
|
||||||
Custom LogEntry model configuration via ``AUDITLOG_LOGENTRY_MODEL``
|
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
|
Actors
|
||||||
------
|
------
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue