Skip to content

Commit c07d907

Browse files
authored
Merge pull request #256 from gbataille/field_list
Field list
2 parents 2035c41 + e54a5fe commit c07d907

File tree

12 files changed

+146
-34
lines changed

12 files changed

+146
-34
lines changed

AUTHORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Authors
3636
- vnagendra
3737
- Lucas Wiman
3838
- Michael England
39+
- Gregory Bataille
3940

4041
Background
4142
==========

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Changes
44
tip (unreleased)
55
----------------
66
- Added --batchsize option to the populate_history management command.
7+
- Add the ability to display object attributes in the history list view to see
8+
what has changed easily
79

810
1.8.2 (2017-01-19)
911
------------------
37.1 KB
Loading

docs/usage.rst

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,39 @@ An example of admin integration for the ``Poll`` and ``Choice`` models:
127127
Changing a history-tracked model from the admin interface will automatically record the user who made the change (see :doc:`/advanced`).
128128

129129

130+
Displaying custom columns in the admin history list view
131+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
132+
133+
By default, the history log displays one line per change containing
134+
135+
* a link to the detail of the object at that point in time
136+
* the date and time the object was changed
137+
* a comment corresponding to the change
138+
* the author of the change
139+
140+
You can add other columns (for example the object's status to see
141+
how it evolved) by adding a ``history_list_display`` array of fields to the
142+
admin class
143+
144+
.. code-block:: python
145+
146+
from django.contrib import admin
147+
from simple_history.admin import SimpleHistoryAdmin
148+
from .models import Poll, Choice
149+
150+
151+
class PollHistoryAdmin(SimpleHistoryAdmin):
152+
list_display = ["id", "name", "status"]
153+
history_list_display = ["status"]
154+
search_fields = ['name', 'user__username']
155+
156+
admin.site.register(Poll, PollHistoryAdmin)
157+
admin.site.register(Choice, SimpleHistoryAdmin)
158+
159+
160+
.. image:: screens/5_history_list_display.png
161+
162+
130163
Querying history
131164
----------------
132165

simple_history/admin.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ def history_view(self, request, object_id, extra_context=None):
5757
history = getattr(model, model._meta.simple_history_manager_attribute)
5858
object_id = unquote(object_id)
5959
action_list = history.filter(**{pk_name: object_id})
60+
history_list_display = getattr(self, "history_list_display", [])
6061
# If no history was found, see whether this object even exists.
6162
try:
6263
obj = model.objects.get(**{pk_name: object_id})
@@ -77,7 +78,8 @@ def history_view(self, request, object_id, extra_context=None):
7778
'root_path': getattr(self.admin_site, 'root_path', None),
7879
'app_label': app_label,
7980
'opts': opts,
80-
'admin_user_view': admin_user_view
81+
'admin_user_view': admin_user_view,
82+
'history_list_display': history_list_display,
8183
}
8284
context.update(extra_context or {})
8385
extra_kwargs = {}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{% load i18n %}
2+
{% load url from simple_history_compat %}
3+
{% load admin_urls %}
4+
{% load getattribute from getattributes %}
5+
6+
<table id="change-history" class="table table-bordered table-striped">
7+
<thead>
8+
<tr>
9+
<th scope="col">{% trans 'Object' %}</th>
10+
{% for column in history_list_display %}
11+
<th scope="col">{% trans column %}</th>
12+
{% endfor %}
13+
<th scope="col">{% trans 'Date/time' %}</th>
14+
<th scope="col">{% trans 'Comment' %}</th>
15+
<th scope="col">{% trans 'Changed by' %}</th>
16+
</tr>
17+
</thead>
18+
<tbody>
19+
{% for action in action_list %}
20+
<tr>
21+
<td><a href="{% url opts|admin_urlname:'simple_history' object.pk action.pk %}">{{ action.history_object }}</a></td>
22+
{% for column in history_list_display %}
23+
<td scope="col">{{ action|getattribute:column }}</th>
24+
{% endfor %}
25+
<td>{{ action.history_date }}</td>
26+
<td>{{ action.get_history_type_display }}</td>
27+
<td>
28+
{% if action.history_user %}
29+
{% url admin_user_view action.history_user_id as admin_user_url %}
30+
{% if admin_user_url %}
31+
<a href="{{ admin_user_url }}">{{ action.history_user }}</a>
32+
{% else %}
33+
{{ action.history_user }}
34+
{% endif %}
35+
{% else %}
36+
{% trans "None" %}
37+
{% endif %}
38+
</td>
39+
</tr>
40+
{% endfor %}
41+
</tbody>
42+
</table>

simple_history/templates/simple_history/object_history.html

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
{% load i18n %}
33
{% load url from simple_history_compat %}
44
{% load admin_urls %}
5+
{% load display_list from simple_history_admin_list %}
56

67

78
{% block content %}
@@ -11,37 +12,7 @@
1112

1213
<div class="module">
1314
{% if action_list %}
14-
<table id="change-history" class="table table-bordered table-striped">
15-
<thead>
16-
<tr>
17-
<th scope="col">{% trans 'Object' %}</th>
18-
<th scope="col">{% trans 'Date/time' %}</th>
19-
<th scope="col">{% trans 'Comment' %}</th>
20-
<th scope="col">{% trans 'Changed by' %}</th>
21-
</tr>
22-
</thead>
23-
<tbody>
24-
{% for action in action_list %}
25-
<tr>
26-
<td><a href="{% url opts|admin_urlname:'simple_history' object.pk action.pk %}">{{ action.history_object }}</a></td>
27-
<td>{{ action.history_date }}</td>
28-
<td>{{ action.get_history_type_display }}</td>
29-
<td>
30-
{% if action.history_user %}
31-
{% url admin_user_view action.history_user_id as admin_user_url %}
32-
{% if admin_user_url %}
33-
<a href="{{ admin_user_url }}">{{ action.history_user }}</a>
34-
{% else %}
35-
{{ action.history_user }}
36-
{% endif %}
37-
{% else %}
38-
{% trans "None" %}
39-
{% endif %}
40-
</td>
41-
</tr>
42-
{% endfor %}
43-
</tbody>
44-
</table>
15+
{% display_list %}
4516
{% else %}
4617
<p>{% trans "This object doesn't have a change history." %}</p>
4718
{% endif %}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from django import template
2+
3+
register = template.Library()
4+
5+
6+
def getattribute(value, arg):
7+
"""Gets an attribute of an object dynamically from a string name"""
8+
9+
return getattr(value, arg, None)
10+
11+
register.filter('getattribute', getattribute)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from django import template
2+
3+
register = template.Library()
4+
5+
6+
@register.inclusion_tag("simple_history/_object_history_list.html",
7+
takes_context=True)
8+
def display_list(context):
9+
return context

simple_history/tests/admin.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@ def has_change_permission(self, request, obj=None):
1111
return False
1212

1313

14+
class ChoiceAdmin(SimpleHistoryAdmin):
15+
history_list_display = ['votes']
16+
17+
1418
admin.site.register(Poll, SimpleHistoryAdmin)
15-
admin.site.register(Choice, SimpleHistoryAdmin)
19+
admin.site.register(Choice, ChoiceAdmin)
1620
admin.site.register(Person, PersonAdmin)
1721
admin.site.register(Book, SimpleHistoryAdmin)
1822
admin.site.register(Document, SimpleHistoryAdmin)

0 commit comments

Comments
 (0)