django-simple-history
django-simple-history stores Django model state on every create/update/delete.
This app supports the following combinations of Django and Python:
Django |
Python |
|---|---|
4.2 |
3.9, 3.10, 3.11, 3.12, 3.13 |
5.0 |
3.10, 3.11, 3.12, 3.13 |
5.1 |
3.10, 3.11, 3.12, 3.13 |
5.2 |
3.10, 3.11, 3.12, 3.13 |
main |
3.12, 3.13 |
Contribute
Issue Tracker: https://github.com/jazzband/django-simple-history/issues
Source Code: https://github.com/jazzband/django-simple-history
Pull requests are welcome.
Documentation
- Quick Start
- Querying History
- Querying history on a model instance
- Querying history on a model class
- Getting previous and next historical record
- Reverting the Model
- as_of
- is_historic and to_historic
- HistoricForeignKey
- HistoricOneToOneField
- most_recent
- Save without creating historical records
- Filtering data using a relationship to the model
- Admin Integration
- Historical Model Customizations
- Custom
history_id - Custom
history_date - Indexed
history_date - Custom history table name
- Custom model name
- Custom History Manager and Historical QuerySets
- TextField as history_change_reason
- Change Base Class of HistoricalRecord Models
- Excluded Fields
- Adding additional fields to historical models
- Change Reason
- Deleting historical record
- Allow tracking to be inherited
- History Model In Different App
- FileField as a CharField
- Drop Database Indices
- Tracking many to many relationships
- Custom
- User Tracking
- Signals
- History Diffing
- Multiple databases
- Utils
- Common Issues
Changes
Unreleased
3.9.0 (2025-01-26)
Removed the
simple_history_admin_list.display_list()template tag that was deprecated in version 3.6.0 (gh-1444)
3.8.0 (2025-01-23)
Made
skip_history_when_savingwork when creating an object - not just when updating an object (gh-1262)Improved performance of the
latest_of_each()history manager method (gh-1360)Fixed issue with deferred fields causing DoesNotExist error (gh-678)
Added HistoricOneToOneField (gh-1394)
Updated all djangoproject.com links to reference the stable version (gh-1420)
Dropped support for Python 3.8, which reached end-of-life on 2024-10-07 (gh-1421)
Added support for Django 5.1 (gh-1388)
Added pagination to
SimpleHistoryAdmin(gh-1277)Fixed issue with history button not working when viewing historical entries in the admin (gh-527)
Added support for Django 5.2 (gh-1441)
simple_history_admin_list.display_list()was planned to be removed in this release, but it was overlooked, and will instead be removed in 3.9.0
3.7.0 (2024-05-29)
Dropped support for Django 3.2, which reached end-of-life on 2024-04-01 (gh-1344)
Removed the temporary requirement on
asgiref>=3.6added in 3.5.0, now that the minimum required Django version is 4.2 (gh-1344)Migrated package building from using the deprecated
setup.pyto usingpyproject.toml(with Hatchling as build backend);setup.pyhas consequently been removed (gh-1348)Added
django>=4.2as an installation dependency, to mirror the minimum version tested in our CI (gh-1349)
3.6.0 (2024-05-26)
Support custom History
ManagerandQuerySetclasses (gh-1280)Renamed the (previously internal) admin template
simple_history/_object_history_list.htmltosimple_history/object_history_list.html, and added the fieldSimpleHistoryAdmin.object_history_list_templatefor overriding it (gh-1128)Deprecated the undocumented template tag
simple_history_admin_list.display_list(); it will be removed in version 3.8 (gh-1128)Added
SimpleHistoryAdmin.get_history_queryset()for overriding whichQuerySetis used to list the historical records (gh-1128)Added
SimpleHistoryAdmin.get_history_list_display()which returnshistory_list_displayby default, and made the latter into an actual field (gh-1128)ModelDeltaandModelChange(insimple_history.models) are now immutable dataclasses; their signatures remain unchanged (gh-1128)ModelDelta’schangesandchanged_fieldsare now sorted alphabetically by field name. Also, ifModelChangeis for an M2M field, itsoldandnewlists are sorted by the related object. This should help prevent flaky tests. (gh-1128)diff_against()has a new keyword argument,foreign_keys_are_objs; see usage in the docs under “History Diffing” (gh-1128)Added a “Changes” column to
SimpleHistoryAdmin’s object history table, listing the changes between each historical record of the object; see the docs under “Customizing the History Admin Templates” for overriding its template context (gh-1128)Fixed the setting
SIMPLE_HISTORY_ENABLED = Falsenot preventing M2M historical records from being created (gh-1328)For history-tracked M2M fields, adding M2M objects (using
add()orset()) used to cause a number of database queries that scaled linearly with the number of objects; this has been fixed to now be a constant number of queries (gh-1333)
3.5.0 (2024-02-19)
Fixed
FieldErrorwhen creating historical records for many-to-many fields withto="self"(gh-1218)Allow
HistoricalRecords.m2m_fieldsas str (gh-1243)Fixed
HistoryRequestMiddlewaredeleting non-existentHistoricalRecords.context.requestin very specific circumstances (gh-1256)Added
custom_historical_attrstobulk_create_with_history()andbulk_update_with_history()for setting additional fields on custom history models (gh-1248)Passing an empty list as the
fieldsargument tobulk_update_with_history()is now allowed; history records will still be created (gh-1248)Added temporary requirement on
asgiref>=3.6while the minimum required Django version is lower than 4.2 (gh-1261)Small performance optimization of the
clean-duplicate_historycommand (gh-1015)Support Simplified Chinese translation (gh-1281)
Added support for Django 5.0 (gh-1283)
Added support for Python 3.13 (gh-1289)
3.4.0 (2023-08-18)
Fixed typos in the docs
Added feature to evaluate
historymodel permissions explicitly whenSIMPLE_HISTORY_ENFORCE_HISTORY_MODEL_PERMISSIONSis set toTrueinsettings(gh-1017).Fixed
SimpleHistoryAdminnot properly integrating with custom user models (gh-1177)Support Indonesian translation (gh-1198)
Support Urdu translation (gh-1199)
Support Norwegian Bokmål translation (gh-1210)
Dropped support for Python 3.7, which reached end-of-life on 2023-06-27 (gh-1202)
Dropped support for Django 4.0, which reached end-of-life on 2023-04-01 (gh-1202)
Added support for Django 4.2 (gh-1202)
Made
bulk_update_with_history()return the number of model rows updated (gh-1206)Fixed
HistoryRequestMiddlewarenot cleaning up after itself (i.e. deletingHistoricalRecords.context.request) under some circumstances (gh-1188)Made
HistoryRequestMiddlewareasync-capable (gh-1209)Fixed error when setting
table_namewithinherit=True(gh-1195)
3.3.0 (2023-03-08)
Made it possible to use the new
m2m_fieldswith model inheritance (gh-1042)Added two signals:
pre_create_historical_m2m_recordsandpost_create_historical_m2m_records(gh-1042)Added
tracked_fieldsattribute to historical models (gh-1038)Fixed
KeyErrorwhen runningclean_duplicate_historyon models withexcluded_fields(gh-1038)Added support for Python 3.11 (gh-1053)
Added Arabic translations (gh-1056)
Fixed a code example under “Tracking many to many relationships” (gh-1069)
Added a
--base-manageroption to theclean_duplicate_historymanagement command (gh-1115)
3.2.0 (2022-09-28)
Fixed typos in the docs
Removed n+1 query from
bulk_create_with_historyutility (gh-975)Started using
existsquery instead ofcountinpopulate_historycommand (gh-982)Add basic support for many-to-many fields (gh-399)
Added support for Django 4.1 (gh-1021)
3.1.1 (2022-04-23)
Full list of changes:
Fix py36 references in pyproject.toml (gh-960)
Fix local setup.py install versioning issue (gh-960)
Remove py2 universal wheel cfg - only py3 needed now (gh-960)
3.1.0 (2022-04-09)
Breaking Changes:
Dropped support for Django 2.2 (gh-968)
Dropped support for Django 3.1 (gh-952)
Dropped support for Python 3.6, which reached end-of-life on 2021-12-23 (gh-946)
Upgrade Implications:
Run makemigrations after upgrading to realize the benefit of indexing changes.
Full list of changes:
Added queryset-based filtering with
as_of(gh-397)Added index on history_date column; opt-out with setting SIMPLE_HISTORY_DATE_INDEX (gh-565)
RecordModels now support a
no_db_indexsetting, to drop indices in historical models, default stays the same (gh-720)Support
included_fieldsforhistory.diff_against(gh-776)Improve performance of
history.diff_againstby reducing number of queries to 0 in most cases (gh-776)Fixed
prev_recordandnext_recordperformance when usingexcluded_fields(gh-791)Fixed update_change_reason in pk (gh-806)
Fixed bug where serializer of djangorestframework crashed if used with
OrderingFilter(gh-821)Fixed make format so it works by using tox (gh-859)
Fixed bug where latest() is not idempotent for identical
history_daterecords (gh-861)Added
excluded_field_kwargsto support customOneToOneFieldthat have additional arguments that don’t exist onForeignKey. (gh-870)Added Czech translations (gh-885)
Added ability to break into debugger on unit test failure (gh-890)
Added pre-commit for better commit quality (gh-896)
Russian translations update (gh-897)
Added support for Django 4.0 (gh-898)
Added Python 3.10 to test matrix (gh-899)
Fix bug with
history.diff_againstwith non-editable fields (gh-923)Added HistoricForeignKey (gh-940)
Support change reason formula feature. Change reason formula can be defined by overriding
get_change_reason_for_objectmethod after subclassingHistoricalRecords(gh-962)
3.0.0 (2021-04-16)
Breaking changes:
Removed support for Django 3.0
Removed changeReason in favor of _change_reason (see 2.10.0)
Full list of changes:
Removed support for Django versions prior to 2.2 (gh-652)
Migrate from TravisCI to Github Actions (gh-739)
Add Python 3.9 support (gh-745)
Support
ignore_conflictsinbulk_create_with_history(gh-733)Use
asgirefwhen available instead of thread locals (gh-747)Sort imports with isort (gh-751)
Queryset
history.as_ofspeed improvements by calculating in the DB (gh-758)Increase black and isort python version to 3.6 (gh-817)
Remove Django 3.0 support (gh-817)
Add Django 3.2 support (gh-817)
Improve French translations (gh-811)
Remove support for changeReason (gh-819)
2.12.0 (2020-10-14)
Add default date to
bulk_create_with_historyandbulk_update_with_history(gh-687)Exclude ManyToManyFields when using
bulk_create_with_history(gh-699)Added
--excluded_fieldsargument toclean_duplicate_historycommand (gh-674)Exclude ManyToManyFields when fetching excluded fields (gh-707)
Use default model manager for
bulk_create_with_historyandbulk_update_with_historyinstead ofobjects(gh-703)Add optional
managerargument tobulk_update_with_historyto use instead of the default manager (gh-703)Add support for Django 3.1 (gh-713)
Fix a bug with
clean_old_historycommand’s –days argument (gh-722)
* NOTE: This will be the last minor release before 3.0.0.
2.11.0 (2020-06-20)
Added
clean_old_historymanagement command (gh-675)Added
user_db_constraintparam to history to avoid circular reference on delete (gh-676)Leverages
get_userfromHistoricalRecordsin order to set a fallback user on bulk update and bulk create (gh-677)
2.10.0 (2020-04-27)
Added
bulk_update_with_historyutility function (gh-650)Add default user and default change reason to
bulk_create_with_historyandbulk_update_with_history(gh-653)Add french translation (gh-654)
Start using
_change_reasoninstead ofchangeReasonto add change reasons to historical objects.changeReasonis deprecated and will be removed in version3.0.0(gh-655)
2.9.0 (2020-04-23)
Add simple filtering if provided a minutes argument in
clean_duplicate_history(gh-606)Add setting to convert
FileFieldtoCharFieldinstead ofTextField(gh-625)Added notes on BitBucket Pipelines (gh-627)
import model
ContentTypeinSimpleHistoryAdminusingdjango_apps.get_modelto avoid possibleAppRegistryNotReadyexception (gh-630)Fix
utils.update_change_reasonwhen user specifies excluded_fields (gh-637)Changed how
nowis imported fromtimezone(timezonemodule is imported now) (gh-643)settings.SIMPLE_HISTORY_REVERT_DISABLEDif True removes the Revert button from the history form for all historical models (gh-632))
2.8.0 (2019-12-02)
Fixed
bulk_create_with_history supportfor HistoryRecords withrelation_nameattribute (gh-591)Added support for
bulk_create_with_historyfor databases different from PostgreSQL (gh-577)Fixed
DoesNotExisterror when trying to get instance if object is deleted (gh-571)Fix
model_to_dictto detect changes in a parent model when usinginherit=True(backwards-incompatible for users who were directly using previous version) (gh-576)Use an iterator for
clean_duplicate_history(gh-604)Add support for Python 3.8 and Django 3.0 (gh-610)
2.7.3 (2019-07-15)
Fixed
BigAutoFieldnot mirrored asBigInt(gh-556)Fixed
most_recent()bug withexcluded_fields(gh-561)Added official Django 2.2 support (gh-555)
2.7.2 (2019-04-17)
Fixed ModuleNotFound issue for
six(gh-553)
2.7.1 (2019-04-16)
Added the possibility to create a relation to the original model (gh-536)
Fix router backward-compatibility issue with 2.7.0 (gh-539, gh-547)
Fix hardcoded history manager (gh-542)
Replace deprecated
django.utils.sixwithsix(gh-526)Allow
custom_model_nameparameter to be a callable (gh-489)
2.7.0 (2019-01-16)
* Add support for
usingchained manager method and save/delete keyword argument (gh-507)Added management command
clean_duplicate_historyto remove duplicate history entries (gh-483)Updated most_recent to work with excluded_fields (gh-477)
Fixed bug that prevented self-referential foreign key from using
'self'(gh-513)Added ability to track custom user with explicit custom
history_user_id_field(gh-511)Don’t resolve relationships for history objects (gh-479)
Reorganization of docs (gh-510)
* NOTE: This change was not backward compatible for users using routers to write history tables to a separate database from their base tables. This issue is fixed in 2.7.1.
2.6.0 (2018-12-12)
Add
appparameter to the constructor ofHistoricalRecords(gh-486)Add
custom_model_nameparameter to the constructor ofHistoricalRecords(gh-451)Fix header on history pages when custom site_header is used (gh-448)
Modify
pre_create_historical_recordto passhistory_instancefor ease of customization (gh-421)Raise warning if
HistoricalRecords(inherit=False)is in an abstract model (gh-341)Ensure custom arguments for fields are included in historical models’ fields (gh-431)
Add german translations (gh-484)
Add
extra_contextparameter to history_form_view (gh-467)Fixed bug that prevented
next_recordandprev_recordto work with custom manager names (gh-501)
2.5.1 (2018-10-19)
Add
'+'as thehistory_typefor each instance inbulk_history_create(gh-449)Add support for
history_change_reasonfor each instance inbulk_history_create(gh-449)Add
history_change_reasonin the history list view under theChange reasondisplay name (gh-458)Fix bug that caused failures when using a custom user model (gh-459)
2.5.0 (2018-10-18)
Add ability to cascade delete historical records when master record is deleted (gh-440)
Added Russian localization (gh-441)
2.4.0 (2018-09-20)
Add pre and post create_historical_record signals (gh-426)
Remove support for
django_mongodb_enginewhen converting AutoFields (gh-432)Add support for Django 2.1 (gh-418)
2.3.0 (2018-07-19)
Add ability to diff
HistoricalRecords(gh-244)
2.2.0 (2018-07-02)
Add ability to specify alternative user_model for tracking (gh-371)
Add util function
bulk_create_with_historyto allow bulk_create with history saved (gh-412)
2.1.1 (2018-06-15)
Fixed out-of-memory exception when running populate_history management command (gh-408)
Fix TypeError on populate_history if excluded_fields are specified (gh-410)
2.1.0 (2018-06-04)
Add ability to specify custom
history_reasonfield (gh-379)Add ability to specify custom
history_idfield (gh-368)Add HistoricalRecord instance properties
prev_recordandnext_record(gh-365)Can set admin methods as attributes on object history change list template (gh-390)
Fixed compatibility of >= 2.0 versions with old-style middleware (gh-369)
2.0 (2018-04-05)
Added Django 2.0 support (gh-330)
Dropped support for Django<=1.10 (gh-356)
Fix bug where
history_viewignored user permissions (gh-361)Fixed
HistoryRequestMiddlewarewhich hadn’t been working for Django>1.9 (gh-364)
1.9.1 (2018-03-30)
Use
get_querysetratherthan model.objectsinhistory_view. (gh-303)Change ugettext calls in models.py to ugettext_lazy
Resolve issue where model references itself (gh-278)
Fix issue with tracking an inherited model (abstract class) (gh-269)
Fix history detail view on django-admin for abstract models (gh-308)
Dropped support for Django<=1.6 and Python 3.3 (gh-292)
1.9.0 (2017-06-11)
Add
--batchsizeoption to thepopulate_historymanagement command. (gh-231)Add ability to show specific attributes in admin history list view. (gh-256)
Add Brazilian Portuguese translation file. (gh-279)
Fix locale file packaging issue. (gh-280)
Add ability to specify reason for history change. (gh-275)
Test against Django 1.11 and Python 3.6. (gh-276)
Add
excluded_fieldsoption to exclude fields from history. (gh-274)
1.8.2 (2017-01-19)
Add Polish locale.
Add Django 1.10 support.
1.8.1 (2016-03-19)
Clear the threadlocal request object when processing the response to prevent test interactions. (gh-213)
1.8.0 (2016-02-02)
History tracking can be inherited by passing
inherit=True. (gh-63)
1.7.0 (2015-12-02)
Add ability to list history in admin when the object instance is deleted. (gh-72)
Add ability to change history through the admin. (Enabled with the
SIMPLE_HISTORY_EDITsetting.)Add Django 1.9 support.
Support for custom tables names. (gh-196)
1.6.3 (2015-07-30)
Respect
to_fieldanddb_columnparameters (gh-182)
1.6.2 (2015-07-04)
Use app loading system and fix deprecation warnings on Django 1.8 (gh-172)
Update Landscape configuration
1.6.1 (2015-04-21)
Fix OneToOneField transformation for historical models (gh-166)
Disable cascading deletes from related models to historical models
Fix restoring historical instances with missing one-to-one relations (gh-162)
1.6.0 (2015-04-16)
Add support for Django 1.8+
Deprecated use of
CustomForeignKeyField(to be removed)Remove default reverse accessor to
auth.Userfor historical models (gh-121)
1.5.4 (2015-01-03)
Fix a bug when models have a
ForeignKeywithprimary_key=TrueDo NOT delete the history elements when a user is deleted.
Add support for
latestAllow setting a reason for change. [using option changeReason]
1.5.3 (2014-11-18)
Fix migrations while using
order_with_respsect_to(gh-140)Fix migrations using south
Allow history accessor class to be overridden in
register()
1.5.2 (2014-10-15)
Additional fix for migrations (gh-128)
1.5.1 (2014-10-13)
Removed some incompatibilities with non-default admin sites (gh-92)
Fixed error caused by
HistoryRequestMiddlewareduring anonymous requests (gh-115 fixes gh-114)Added workaround for clashing related historical accessors on User (gh-121)
Added support for MongoDB AutoField (gh-125)
Fixed CustomForeignKeyField errors with 1.7 migrations (gh-126 fixes gh-124)
1.5.0 (2014-08-17)
Extended availability of the
as_ofmethod to models as well as instances.Allow
history_useron historical objects to be set by middleware.Fixed error that occurs when a foreign key is designated using just the name of the model.
Drop Django 1.3 support
1.4.0 (2014-06-29)
Fixed error that occurs when models have a foreign key pointing to a one to one field.
Fix bug when model verbose_name uses unicode (gh-76)
Allow non-integer foreign keys
Allow foreign keys referencing the name of the model as a string
Added the ability to specify a custom
history_dateNote that
simple_historyshould be added toINSTALLED_APPS(gh-94 fixes gh-69)Properly handle primary key escaping in admin URLs (gh-96 fixes gh-81)
Add support for new app loading (Django 1.7+)
Allow specifying custom base classes for historical models (gh-98)
1.3.0 (2013-05-17)
Fixed bug when using
django-simple-historyon nested models packageAllow history table to be formatted correctly with
django-admin-bootstrapDisallow calling
simple_history.registertwice on the same modelAdded Python 3 support
Added support for custom user model (Django 1.5+)
1.2.3 (2013-04-22)
Fixed packaging bug: added admin template files to PyPI package
1.2.1 (2013-04-22)
Added tests
Added history view/revert feature in admin interface
Various fixes and improvements
Oct 22, 2010
Merged setup.py from Klaas van Schelven - Thanks!
Feb 21, 2010
Initial project creation, with changes to support ForeignKey relations.