mirror of
https://github.com/jazzband/django-auditlog.git
synced 2026-03-16 22:20:26 +00:00
Audit changes to FK fields when saved using *_id naming. (#525)
* Audit changes to FK fields when saved using *_id naming.
In Django you can save changes to a FK field on a model using the ID
field name (attname) in addition to the regular FK field name with:
model.related_model_id = 42
model.save(update_fields=["related_model_id'])
or:
model.related_model = related_model
model.save(update_fields=["related_model_id'])
as opposed to the more common:
model.related_model = related_model
model.save(update_fields=["related_model'])
This change ensures those model changes are logged properly.
* Apply suggested change from code review.
* Add a CHANGELOG entry for the fix.
This commit is contained in:
parent
fa955cd5c7
commit
cd0d3ea311
3 changed files with 36 additions and 2 deletions
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#### Fixes
|
||||
|
||||
- fix: Audit changes to FK fields when saved using `*_id` naming. ([#525](https://github.com/jazzband/django-auditlog/pull/525))
|
||||
- fix: Fix a bug in audit log admin page when `USE_TZ=False`. ([#511](https://github.com/jazzband/django-auditlog/pull/511))
|
||||
- fix: Make sure `LogEntry.changes_dict()` returns an empty dict instead of `None` when `json.loads()` returns `None`. ([#472](https://github.com/jazzband/django-auditlog/pull/472))
|
||||
- fix: Always set remote_addr even if the request has no authenticated user. ([#484](https://github.com/jazzband/django-auditlog/pull/484))
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from typing import Optional
|
|||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db.models import NOT_PROVIDED, DateTimeField, JSONField, Model
|
||||
from django.db.models import NOT_PROVIDED, DateTimeField, ForeignKey, JSONField, Model
|
||||
from django.utils import timezone as django_timezone
|
||||
from django.utils.encoding import smart_str
|
||||
|
||||
|
|
@ -147,7 +147,14 @@ def model_instance_diff(
|
|||
model_fields = None
|
||||
|
||||
if fields_to_check:
|
||||
fields = {field for field in fields if field.name in fields_to_check}
|
||||
fields = {
|
||||
field
|
||||
for field in fields
|
||||
if (
|
||||
(isinstance(field, ForeignKey) and field.attname in fields_to_check)
|
||||
or (field.name in fields_to_check)
|
||||
)
|
||||
}
|
||||
|
||||
# Check if fields must be filtered
|
||||
if (
|
||||
|
|
|
|||
|
|
@ -1858,6 +1858,32 @@ class TestRelatedDiffs(TestCase):
|
|||
self.assertEqual(int(log_one.changes_dict["one_to_one"][1]), simple.id)
|
||||
self.assertEqual(int(log_two.changes_dict["related"][1]), two_simple.id)
|
||||
|
||||
def test_log_entry_changes_on_fk_object_id_update(self):
|
||||
t1 = self.test_date
|
||||
with freezegun.freeze_time(t1):
|
||||
simple = SimpleModel.objects.create()
|
||||
one_simple = SimpleModel.objects.create()
|
||||
two_simple = SimpleModel.objects.create()
|
||||
instance = RelatedModel.objects.create(
|
||||
one_to_one=simple, related=one_simple
|
||||
)
|
||||
|
||||
t2 = self.test_date + datetime.timedelta(days=20)
|
||||
with freezegun.freeze_time(t2):
|
||||
instance.related_id = two_simple.id
|
||||
instance.one_to_one = one_simple
|
||||
instance.save(update_fields=["related_id", "one_to_one_id"])
|
||||
|
||||
log_one = instance.history.filter(timestamp=t1).first()
|
||||
log_two = instance.history.filter(timestamp=t2).first()
|
||||
self.assertTrue(isinstance(log_one, LogEntry))
|
||||
self.assertTrue(isinstance(log_two, LogEntry))
|
||||
|
||||
self.assertEqual(int(log_one.changes_dict["related"][1]), one_simple.id)
|
||||
self.assertEqual(int(log_one.changes_dict["one_to_one"][1]), simple.id)
|
||||
self.assertEqual(int(log_two.changes_dict["related"][1]), two_simple.id)
|
||||
self.assertEqual(int(log_two.changes_dict["one_to_one"][1]), one_simple.id)
|
||||
|
||||
def test_log_entry_changes_on_fk_id_update(self):
|
||||
t1 = self.test_date
|
||||
with freezegun.freeze_time(t1):
|
||||
|
|
|
|||
Loading…
Reference in a new issue