Add option to exclude reverse relations from model diffs

Add AUDITLOG_EXCLUDE_REVERSE_RELATIONS setting which, when True,
excludes auto-created reverse relation fields (auto_created and not concrete)
from the diff calculation to avoid extra DB hits and inadvertent mutation
of instance._state.fields_cache.

Closes #551 (or: Fixes behavior described in jazzband/django-auditlog#551).
This commit is contained in:
peyman 2025-10-09 14:11:21 +03:30
parent 85056b73c3
commit ee278edc8f
3 changed files with 25 additions and 0 deletions

View file

@ -21,6 +21,11 @@ settings.AUDITLOG_EXCLUDE_TRACKING_FIELDS = getattr(
settings, "AUDITLOG_EXCLUDE_TRACKING_FIELDS", ()
)
# Exclude reverse relation fields across all models
settings.AUDITLOG_EXCLUDE_REVERSE_RELATIONS = getattr(
settings, "AUDITLOG_EXCLUDE_REVERSE_RELATIONS", False
)
# Mask named fields across all models
settings.AUDITLOG_MASK_TRACKING_FIELDS = getattr(
settings, "AUDITLOG_MASK_TRACKING_FIELDS", ()

View file

@ -213,6 +213,16 @@ def model_instance_diff(
fields = set()
model_fields = None
# Optionally exclude reverse relations (auto-created fields).
# Reverse relations (auto_created & not concrete) can cause unwanted DB hits
# and mutate instance._state.fields_cache as a side-effect.
# Make this behavior opt-in via AUDITLOG_EXCLUDE_REVERSE_RELATIONS.
if settings.AUDITLOG_EXCLUDE_REVERSE_RELATIONS:
def is_reverse_field(f):
return getattr(f, "auto_created", False) and not getattr(f, "concrete", False)
fields = {f for f in fields if not is_reverse_field(f)}
if fields_to_check:
fields = {
field

View file

@ -574,3 +574,13 @@ The mixin provides the following configuration options:
- ``auditlog_history_template``: Template to use for rendering the history page (default: ``auditlog/object_history.html``)
- ``auditlog_history_per_page``: Number of log entries to display per page (default: 10)
.. versionadded:: 3.2.2
Default: False
Use ``AUDITLOG_EXCLUDE_REVERSE_RELATIONS`` to exclude reverse relation fields (auto-created fields
where `field.auto_created is True` and `field.concrete is False`) when computing
model diffs. This avoids accidental database queries for related objects and avoids
mutating `instance._state.fields_cache` as a side-effect.
Added to address: https://github.com/jazzband/django-auditlog/issues/551