When I inherit from admin.ModelAdmin, in history on admin page I can see what fields has been changed. However, now I need to use django-simple-history to track all my model changes. Now, for admin, I inherit for simple_history.SimpleHistoryAdmin. Whilst I can see all of the model changes and revert them, I cannot see, which fields were changed. Is it possible to add that handy functionality to SimpleHistoryAdmin?
6 Answers
I found a way to solve this issue. I added a ModelAdmin method and used History Diffing to add a custom field in the Change history table.
history_list_display = ['changed_fields']
def changed_fields(self, obj):
if obj.prev_record:
delta = obj.diff_against(obj.prev_record)
return delta.changed_fields
return None

- 467
- 6
- 17
What you need is history_list_display
field in your Admin. The list of fields included in the history_list_display
will be displayed in the history page with their corresponding entries.
Something like this:
class SomeAdmin(admin.ModelAdmin):
def some_user_defined(self, obj):
return "something"
date_hierarchy = 'created_at'
search_fields = ['field1', 'field2']
list_display = ('field1', 'field2',)
list_filter = ('field1',)
history_list_display = ('field1', 'field2', 'some_user_defined',)
This will display field1
, field2
along with comment
, user
and reason

- 1,690
- 15
- 17
You probably want to do something like that:
# admin.py
from django.contrib import admin
from simple_history.admin import SimpleHistoryAdmin
from .models import Website
from django.utils.html import format_html
class WebsiteHistoryAdmin(SimpleHistoryAdmin):
history_list_display = ["changed_fields","list_changes"]
def changed_fields(self, obj):
if obj.prev_record:
delta = obj.diff_against(obj.prev_record)
return delta.changed_fields
return None
def list_changes(self, obj):
fields = ""
if obj.prev_record:
delta = obj.diff_against(obj.prev_record)
for change in delta.changes:
fields += str("<strong>{}</strong> changed from <span style='background-color:#ffb5ad'>{}</span> to <span style='background-color:#b3f7ab'>{}</span> . <br/>".format(change.field, change.old, change.new))
return format_html(fields)
return None
admin.site.register(Website, WebsiteHistoryAdmin)
And you get this as a result:

- 359
- 4
- 7
And if you want to view not only names of changed fields as per Rafi comment and also changed values, next code will do it:
def changed_fields_with_values(self, obj):
fields = ""
if obj.prev_record:
delta = obj.diff_against(obj.prev_record)
for change in delta.changes:
fields += str("{} changed from {} to {}".format(change.field, change.old, change.new))
return fields
return None

- 56
- 1
- 3
Similar to the previous solution from Rafi but using array to list more elegantly the record changes:
def list_changes(self, obj):
diff = []
if obj.prev_record:
delta = obj.diff_against(obj.prev_record)
for change in delta.changes:
diff.append("<b>* {}:</b> changed from `{}` to `{}`".format(change.field, change.old, change.new))
return mark_safe("\n<br>".join(diff))

- 291
- 2
- 6
Adding on to what @Rafi suggested, I created a class for this that I can use as a mixin:
class EnhancedSimpleHistoryAdmin(SimpleHistoryAdmin):
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
if hasattr(cls, 'history_list_display'):
cls.history_list_display.append('changed_fields')
else:
cls.history_list_display = ['changed_fields']
def changed_fields(self, obj):
if obj.prev_record:
delta = obj.diff_against(obj.prev_record)
return ", ".join(delta.changed_fields)
return None

- 8,121
- 3
- 30
- 44