Skip to content

Commit f9d5d1e

Browse files
committed
compare only specific fields when diffing between m2m relations
1 parent 0700691 commit f9d5d1e

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

simple_history/models.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -901,9 +901,29 @@ def diff_against(self, old_history, excluded_fields=None, included_fields=None):
901901
changes.append(ModelChange(field, old_value, current_value))
902902
changed_fields.append(field)
903903

904+
# Separately compare m2m fields:
904905
for field in old_history._history_m2m_fields:
905-
old_rows = list(getattr(old_history, field.name).values_list())
906-
new_rows = list(getattr(self, field.name).values_list())
906+
# First retrieve a single item to get the field names from:
907+
reference_history_m2m_item = (
908+
getattr(old_history, field.name).first()
909+
or getattr(self, field.name).first()
910+
)
911+
history_field_names = []
912+
if reference_history_m2m_item:
913+
# Create a list of field names to compare against.
914+
# The list is generated without the primary key of the intermediate
915+
# table, the foreign key to the history record, and the actual 'history'
916+
# field, to avoid false positives while diffing.
917+
history_field_names = [
918+
f.name
919+
for f in reference_history_m2m_item._meta.fields
920+
if f.editable and f.name not in ["id", "m2m_history_id", "history"]
921+
]
922+
923+
old_rows = list(
924+
getattr(old_history, field.name).values(*history_field_names)
925+
)
926+
new_rows = list(getattr(self, field.name).values(*history_field_names))
907927

908928
if old_rows != new_rows:
909929
change = ModelChange(field.name, old_rows, new_rows)

simple_history/tests/tests/test_models.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,7 +2009,9 @@ def test_diff_against(self):
20092009
add_record, create_record = self.poll.history.all()
20102010

20112011
delta = add_record.diff_against(create_record)
2012-
expected_change = ModelChange("places", [], [(1, 1, 2, 1, 1)])
2012+
expected_change = ModelChange(
2013+
"places", [], [{"pollwithmanytomany": 1, "place": 1}]
2014+
)
20132015
self.assertEqual(delta.changed_fields, ["places"])
20142016
self.assertEqual(delta.old_record, create_record)
20152017
self.assertEqual(delta.new_record, add_record)
@@ -2027,7 +2029,9 @@ def test_diff_against(self):
20272029

20282030
# Second and third should have the same diffs as first and second, but with
20292031
# old and new reversed
2030-
expected_change = ModelChange("places", [(1, 1, 2, 1, 1)], [])
2032+
expected_change = ModelChange(
2033+
"places", [{"place": 1, "pollwithmanytomany": 1}], []
2034+
)
20312035
delta = del_record.diff_against(add_record)
20322036
self.assertEqual(delta.changed_fields, ["places"])
20332037
self.assertEqual(delta.old_record, add_record)

0 commit comments

Comments
 (0)