回答:
管理履歴は、他のDjangoアプリと同様のアプリですが、管理サイトでの特別な配置は例外です。
モデルはdjango.contrib.admin.models.LogEntryにあります。
ユーザーが変更を加えたら、次のようにログに追加します(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
)
object
もちろん、変更されたオブジェクトはどこですか。
今、私はダニエルの答えを見て、彼に同意します、それはかなり制限されています。
私の意見では、より強力なアプローチは、Marty Alchinのコードを彼の著書Pro Djangoで使用することです(263ページから始まる履歴レコードの保持を参照)。このアプローチを実装および拡張するアプリケーションdjango-simple-historyがあります(ドキュメントはこちら)。
from django.utils.encoding import force_unicode
「force_unicode」の場合
管理者の変更履歴ログがで定義されているdjango.contrib.admin.models
、とありますhistory_view
標準のメソッドModelAdmin
クラスが。
それらは特に賢いわけではなく、管理者とかなり密接に結びついているので、アイデアにこれらを使用し、アプリ用に独自のバージョンを作成するのが最善です。
私はこの質問が古いことを知っていますが、今日(Django 1.9)の時点で、Djangoの履歴アイテムはこの質問の日付よりも堅牢です。現在のプロジェクトでは、最近の履歴アイテムを取得して、ナビゲーションバーからドロップダウンに配置する必要がありました。これは私がそれをした方法であり、非常に簡単でした:
*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})
上記のコードスニペットに見られるように、私はLogEntryモデル(django.contrib.admin.models.pyはdjango 1.9にある場所)から基本的なクエリセットを作成し、変更が含まれていないアイテムを除外して、アクション時間と過去20件のログのみを表示します。数だけの別のアイテムも入手しています。LogEntryモデルを見ると、必要なデータをプルバックするためにDjangoが使用したフィールド名がわかります。私の特定のケースでは、これが私のテンプレートで使用したものです:
*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>
すでに述べられていることを追加するために、ここにあなたのための他のいくつかのリソースがあります:
(1)私はdjango-reversionというアプリを使用していて、管理履歴を「フック」して実際に追加しています。あなたがいくつかのサンプルコードが欲しいなら、それは見るのに良い場所でしょう。
(2)独自の履歴機能をロールすることを決定した場合、djangoは、各履歴オブジェクトのpost_saveなど、アプリを処理するためにサブスクライブできるシグナルを提供します。コードは、履歴ログエントリが保存されるたびに実行されます。Doc: Djangoシグナル
こんにちは、
最近、サーバーインベントリデータベースの「更新」ビューにログを記録しました。私の「サンプル」コードを共有すると思いました。以下の関数は、「サーバー」オブジェクトの1つ、変更されたもののリスト、ADDITIONまたはCHANGEのaction_flagを取ります。ADDITIONが「新しいサーバーの追加」を意味する場合、それは少し単純化します。より柔軟なアプローチでは、サーバーに属性を追加できます。もちろん、変更が実際に行われたかどうかを判断するために既存の機能を監査することは十分に困難でした。そのため、新しい属性を「変更」としてログに記録できることを嬉しく思います。
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."