Link to Django admin model history

Setup:

  • I am working on a Django application that allows users to create an object in a database and then come back and edit it as much as they want.
  • The Django admin site keeps a history of changes made to objects through the admin site.

Question:

  • How to connect my application to the administrator’s site change history so that I can see the history of changes made by users to their “content”?
+72
django django-models django-admin
Jun 12 '09 at 16:32
source share
5 answers

Admin history is just an application similar to any other Django application, except for special posting on the admin site.

The model is located in django.contrib.admin.models.LogEntry.

When the user makes changes, add to a logbook similar to this one (stolen shamelessly from contrib / admin / options.py:

from django.contrib.admin.models import LogEntry, ADDITION LogEntry.objects.log_action( user_id = request.user.pk, content_type_id = ContentType.objects.get_for_model(object).pk, object_id = object.pk, object_repr = force_unicode(object), action_flag = ADDITION ) 

where object is the object that has been modified, of course.

Now I see that Daniel answers and agrees with him, he is rather limited.

In my opinion, a stronger approach is to use Marty Alchin's code in his book Pro Django (see Saving Historical Records , starting on page 263). There is a django-simple-history application that implements and extends this approach ( docs here ).

+112
Jun 12 '09 at 18:20
source share

The admin change history log is defined in django.contrib.admin.models , and the standard ModelAdmin class has a history_view method.

They are not particularly smart, although they are quite closely associated with the administrator, so it may be best for you to use them for ideas and create your own version for your application.

+21
Jun 12 '09 at 18:13
source share

To add to the above, here are some other resources for you:

(1) I worked with an application called django-reversion , which “hooked” the history of admins and actually added to it, if you need a sample code that will be a good place to view it.

(2) If you decide to flip your own historical functionality, django provides signals that you could subscribe to in order to have your own application descriptor, for example post_save for each history object. Your code will run every time a history log entry is saved. Doc: Django Signals

+7
Jul 31. '09 at
source share

I know this question is old, but today (Django 1.9) the elements of Django history are more reliable than the date of this question. In the current project, I needed to get the last elements of the story and put them in a drop-down list from the navigation panel. Here is how I did it and was very simple:

 *views.py* from django.contrib.admin.models import LogEntry, ADDITION, CHANGE, DELETION def main(request, template): logs = LogEntry.objects.exclude(change_message="No fields changed.").order_by('-action_time')[:20] logCount = LogEntry.objects.exclude(change_message="No fields changed.").order_by('-action_time')[:20].count() return render(request, template, {"logs":logs, "logCount":logCount}) 

As you can see from the above code snippet, I am creating a basic set of queries from the LogEntry model (django.contrib.admin.models.py is the place where it is in django 1.9) and excluding elements that have no changes, ordering it in time actions and displaying only the last 20 logs. I also get another counting item. If you look at the LogEntry model, you can see the field names that Django used to discard the pieces of data needed. For my specific case, here is what I used in my template:

Link to the image of the final product

 *template.html* <ul class="dropdown-menu"> <li class="external"> <h3><span class="bold">{{ logCount }}</span> Notification(s) </h3> <a href="{% url 'index' %}"> View All </a> </li> {% if logs %} <ul class="dropdown-menu-list scroller actionlist" data-handle-color="#637283" style="height: 250px;"> {% for log in logs %} <li> <a href="javascript:;"> <span class="time">{{ log.action_time|date:"m/d/Y - g:ia" }} </span> <span class="details"> {% if log.action_flag == 1 %} <span class="label label-sm label-icon label-success"> <i class="fa fa-plus"></i> </span> {% elif log.action_flag == 2 %} <span class="label label-sm label-icon label-info"> <i class="fa fa-edit"></i> </span> {% elif log.action_flag == 3 %} <span class="label label-sm label-icon label-danger"> <i class="fa fa-minus"></i> </span> {% endif %} {{ log.content_type|capfirst }}: {{ log }} </span> </a> </li> {% endfor %} </ul> {% else %} <p>{% trans "This object doesn't have a change history. It probably wasn't added via this admin site." %}</p> {% endif %} </li> </ul> 
+7
Mar 06 '16 at 21:58
source share

Code example

Hello,

I recently hacked some “update” entries for our server inventory database. I decided that I would share my "sample" code. The following function takes one of our Server objects, a list of things that have been changed, and action_flag is either ADDITION or CHANGE. This makes it easy to work with a few bits, where ADDITION means "added new server." A more flexible approach will allow adding an attribute to the server. Of course, it was difficult enough to check our existing functions to determine whether the changes really occurred, so I'm happy enough to register the new attributes as “changes”.

 from django.contrib.admin.models import LogEntry, User, ADDITION, CHANGE from django.contrib.contenttypes.models import ContentType def update_server_admin_log(server, updated_list, action_flag): """Log changes to Admin log.""" if updated_list or action_flag == ADDITION: if action_flag == ADDITION: change_message = "Added server %s with hostname %s." % (server.serial, server.name) # http://dannyman.toldme.com/2010/06/30/python-list-comma-comma-and/ elif len(updated_list) > 1: change_message = "Changed " + ", ".join(map(str, updated_list[:-1])) + " and " + updated_list[-1] + "." else: change_message = "Changed " + updated_list[0] + "." # http://stackoverflow.com/questions/987669/tying-in-to-django-admins-model-history try: LogEntry.objects.log_action( # The "update" user added just for this purpose -- you probably want request.user.id user_id = User.objects.get(username='update').id, content_type_id = ContentType.objects.get_for_model(server).id, object_id = server.id, # HW serial number of our local "Server" object -- definitely change when adapting ;) object_repr = server.serial, change_message = change_message, action_flag = action_flag, ) except: print "Failed to log action." 
+2
Jul 07 '10 at 13:25
source share



All Articles