Das Setup:
Die Frage:
Der Admin-Verlauf ist nur eine App wie jede andere Django App, mit der Ausnahme einer speziellen Platzierung auf der Admin-Site.
Das Modell befindet sich in Django.contrib.admin.models.LogEntry.
Wenn ein Benutzer eine Änderung vornimmt, fügen Sie diese dem Protokoll hinzu (schamlos aus contrib/admin/options.py gestohlen):
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
)
dabei ist object
das Objekt, das natürlich geändert wurde.
Jetzt sehe ich Daniels Antwort und stimme ihm zu, es ist ziemlich begrenzt.
Meiner Meinung nach besteht ein stärkerer Ansatz darin, den Code von Marty Alchin in seinem Buch zu verwenden Pro Django (siehe Historische Aufzeichnungen führen auf Seite 263). Es gibt eine Anwendung Django-simple-history , die diesen Ansatz implementiert und erweitert ( docs here ).
Das Änderungsprotokoll des Administrators ist in Django.contrib.admin.models
Definiert, und in der Standardklasse ModelAdmin
gibt es eine Methode history_view
.
Sie sind jedoch nicht besonders clever und ziemlich eng mit dem Administrator verbunden. Verwenden Sie sie daher am besten, um Ideen zu sammeln und eine eigene Version für Ihre App zu erstellen.
Ich weiß, dass diese Frage alt ist, aber seit heute (Django 1.9) sind die historischen Elemente von Django robuster als zum Zeitpunkt dieser Frage. In einem aktuellen Projekt musste ich die letzten Verlaufselemente abrufen und sie über die Navigationsleiste in ein Dropdown-Menü einfügen. So habe ich es gemacht und war sehr direkt:
*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})
Wie im obigen Code-Snippet zu sehen, erstelle ich ein grundlegendes Abfrageset aus dem LogEntry-Modell (Django.contrib.admin.models.py befindet sich dort, wo Django 1.9)) die Elemente ausschließt Wenn es sich um keine Änderungen handelt, die nach Aktionszeit geordnet sind und nur die letzten 20 Protokolle anzeigen, wird ein weiteres Element nur mit der Anzahl angezeigt. Wenn Sie sich das LogEntry-Modell ansehen, sehen Sie die Feldnamen, die Django hat verwendet, um die benötigten Daten zurückzugewinnen. In meinem speziellen Fall habe ich Folgendes in meiner Vorlage verwendet:
*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>
Im Folgenden finden Sie einige weitere Ressourcen, um das Gesagte zu ergänzen:
(1) Ich habe mit einer App namens Django-reversion gearbeitet, die sich in den Admin-Verlauf einhakt und ihn tatsächlich erweitert. Wenn Sie einen Beispielcode wünschen, ist dies ein guter Ort, um nachzuschauen.
(2) Wenn Sie sich dazu entschlossen haben, Ihre eigene Verlaufsfunktion zu erstellen Django liefert Signale, die Sie abonnieren können, damit Ihre App beispielsweise für jedes Verlaufsobjekt post_save ausführt. Ihr Code wird jedes Mal ausgeführt Ein Eintrag im Verlaufsprotokoll wurde gespeichert. Doc: Django-Signale
Hallo,
Ich habe vor kurzem einige Logs in eine "Update" -Ansicht für unsere Server-Inventardatenbank gehackt. Ich dachte, ich würde meinen "Beispiel" -Code teilen. Die folgende Funktion verwendet eines unserer "Server" -Objekte, eine Liste der geänderten Elemente und ein action_flag von ADDITION oder CHANGE. Es vereinfacht die Dinge ein kleines bisschen, wo ADDITION "einen neuen Server hinzugefügt" bedeutet. Ein flexiblerer Ansatz würde das Hinzufügen eines Attributs zu einem Server ermöglichen. Natürlich war es eine ausreichende Herausforderung, unsere vorhandenen Funktionen zu überprüfen, um festzustellen, ob tatsächlich Änderungen vorgenommen wurden. Daher bin ich glücklich, neue Attribute als "Änderung" zu protokollieren.
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."