theme template personalizar password filter_horizontal bootstrap django django-models django-admin

template - Atando al historial de modelos del administrador de Django



django-admin command (5)

Código de ejemplo

Hola,

Recientemente, pirateé un poco el registro en una vista de "actualización" para nuestra base de datos de inventario del servidor. Pensé que compartiría mi código de "ejemplo". La función que sigue toma uno de nuestros objetos "Servidor", una lista de cosas que han sido cambiadas, y un indicador de acción de ADICIÓN o CAMBIO. Simplifica un poco las cosas, donde ADDITION significa "agregó un nuevo servidor". Un enfoque más flexible permitiría agregar un atributo a un servidor. Por supuesto, fue suficientemente desafiante para auditar nuestras funciones existentes para determinar si realmente se habían producido cambios, por lo que estoy feliz de registrar nuevos atributos como un "cambio".

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."

La puesta en marcha:

  • Estoy trabajando en una aplicación de Django que permite a los usuarios crear un objeto en la base de datos y luego regresar y editarlo tanto como lo deseen.
  • El sitio de administración de Django mantiene un historial de los cambios realizados en los objetos a través del sitio de administración.

La pregunta:

  • ¿Cómo conecto mi aplicación al historial de cambios del sitio de administración para que pueda ver el historial de cambios que los usuarios realizan en su "contenido"?

El historial de administración es solo una aplicación como cualquier otra aplicación de Django, con la excepción de una ubicación especial en el sitio de administración.

El modelo está en django.contrib.admin.models.LogEntry.

Cuando un usuario hace un cambio, agréguelo al registro de esta manera (robado descaradamente de 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 )

donde el object es el objeto que ha cambiado, por supuesto.

Ahora que veo la respuesta de Daniel y estoy de acuerdo con él, es bastante limitada.

En mi opinión, un enfoque más sólido es usar el código de Marty Alchin en su libro Pro Django (ver Mantener Registros Históricos a partir de la página 263). Hay una aplicación django-simple-history que implementa y amplía este enfoque ( documentos aquí ).


El registro del historial de cambios del administrador se define en django.contrib.admin.models , y hay un método history_view en la clase ModelAdmin estándar.

Sin embargo, no son particularmente inteligentes, y están estrechamente relacionados con el administrador, por lo que es mejor que los utilice para obtener ideas y crear su propia versión para su aplicación.


Para agregar a lo que ya se ha dicho, estos son algunos otros recursos para usted:

(1) He estado trabajando con una aplicación llamada django-reversion que ''engancha'' al historial de administración y realmente se agrega a ella. Si desea un código de muestra que sería un buen lugar para buscar.

(2) Si decidió desplegar su propia funcionalidad de historial, django proporciona señales a las que podría suscribirse para que su aplicación se maneje, por ejemplo, post_save para cada objeto de historial. Su código se ejecutará cada vez que se guarde una entrada de registro histórico. Doc: señales de Django


Sé que esta pregunta es antigua, pero a partir de hoy (Django 1.9), los elementos de la historia de Django son más sólidos que en la fecha de esta pregunta. En un proyecto actual, necesitaba obtener los elementos del historial reciente y ponerlos en un menú desplegable de la barra de navegación. Así es como lo hice y fue muy directo:

*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})

Como se ve en el fragmento de código anterior, estoy creando un conjunto de consulta básico del modelo LogEntry (django.contrib.admin.models.py es donde está ubicado en django 1.9) y excluyo los elementos donde no hay cambios involucrados, ordenándolo por el tiempo de acción y solo muestra los últimos 20 registros. También estoy recibiendo otro artículo con solo el conteo. Si observa el modelo LogEntry, puede ver los nombres de campo que Django ha utilizado para recuperar los datos que necesita. Para mi caso específico, esto es lo que utilicé en mi plantilla:

Enlace a la imagen del producto final

*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>