Skip to content

Commit eff5796

Browse files
committed
Added tracked_fields attr to historical models
This attribute can be useful for future code and for users, as there is currently no easy way (known to me) to list the fields of a model that are tracked (i.e. not excluded) by a history model. The attribute will also be used in an upcoming bugfix, which was the main motivation for adding this.
1 parent 6692985 commit eff5796

File tree

4 files changed

+51
-6
lines changed

4 files changed

+51
-6
lines changed

CHANGES.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Unreleased
99
- Started using ``exists`` query instead of ``count`` in ``populate_history`` command (gh-982)
1010
- Add basic support for many-to-many fields (gh-399)
1111
- Added support for Django 4.1 (gh-1021)
12+
- Added ``tracked_fields`` attribute to historical models (gh-1038)
1213

1314
3.1.1 (2022-04-23)
1415
------------------

simple_history/manager.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,8 @@ def most_recent(self):
155155
)
156156
)
157157
tmp = []
158-
excluded_fields = getattr(self.model, "_history_excluded_fields", [])
159158

160-
for field in self.instance._meta.fields:
161-
if field.name in excluded_fields:
162-
continue
159+
for field in self.model.tracked_fields:
163160
if isinstance(field, models.ForeignKey):
164161
tmp.append(field.name + "_id")
165162
else:
@@ -263,8 +260,7 @@ def bulk_history_create(
263260
history_type=history_type,
264261
**{
265262
field.attname: getattr(instance, field.attname)
266-
for field in instance._meta.fields
267-
if field.name not in self.model._history_excluded_fields
263+
for field in self.model.tracked_fields
268264
},
269265
)
270266
if hasattr(self.model, "history_relation"):

simple_history/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ def create_history_model(self, model, inherited):
274274
"__module__": self.module,
275275
"_history_excluded_fields": self.excluded_fields,
276276
"_history_m2m_fields": self.get_m2m_fields_from_model(model),
277+
"tracked_fields": self.fields_included(model),
277278
}
278279

279280
app_module = "%s.models" % model._meta.app_label

simple_history/tests/tests/test_models.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
InheritedRestaurant,
7878
Library,
7979
ManyToManyModelOther,
80+
ModelWithCustomAttrOneToOneField,
8081
ModelWithExcludedManyToMany,
8182
ModelWithFkToModelWithHistoryUsingBaseModelDb,
8283
ModelWithHistoryInDifferentDb,
@@ -93,6 +94,7 @@
9394
PollChildBookWithManyToMany,
9495
PollChildRestaurantWithManyToMany,
9596
PollInfo,
97+
PollWithAlternativeManager,
9698
PollWithExcludedFieldsWithDefaults,
9799
PollWithExcludedFKField,
98100
PollWithExcludeFields,
@@ -905,6 +907,51 @@ def create_history_model(model, inherited):
905907
records.module = model.__module__
906908
return records.create_history_model(model, inherited)
907909

910+
def test_create_history_model_has_expected_tracked_files_attr(self):
911+
def assert_tracked_fields_equal(model, expected_field_names):
912+
from .. import models
913+
914+
history_model = getattr(
915+
models, f"Historical{model.__name__}"
916+
)
917+
self.assertListEqual(
918+
[field.name for field in history_model.tracked_fields],
919+
expected_field_names,
920+
)
921+
922+
assert_tracked_fields_equal(
923+
Poll,
924+
["id", "question", "pub_date"],
925+
)
926+
assert_tracked_fields_equal(
927+
PollWithNonEditableField,
928+
["id", "question", "pub_date", "modified"],
929+
)
930+
assert_tracked_fields_equal(
931+
PollWithExcludeFields,
932+
["id", "question", "place"],
933+
)
934+
assert_tracked_fields_equal(
935+
PollWithExcludedFieldsWithDefaults,
936+
["id", "question"],
937+
)
938+
assert_tracked_fields_equal(
939+
PollWithExcludedFKField,
940+
["id", "question", "pub_date"],
941+
)
942+
assert_tracked_fields_equal(
943+
PollWithAlternativeManager,
944+
["id", "question", "pub_date"],
945+
)
946+
assert_tracked_fields_equal(
947+
PollWithHistoricalIPAddress,
948+
["id", "question", "pub_date"],
949+
)
950+
assert_tracked_fields_equal(
951+
ModelWithCustomAttrOneToOneField,
952+
["id", "poll"],
953+
)
954+
908955
def test_create_history_model_with_one_to_one_field_to_integer_field(self):
909956
try:
910957
self.create_history_model(AdminProfile, False)

0 commit comments

Comments
 (0)