История администратора - это просто приложение, как и любое другое приложение 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
объект, который, конечно, был изменен.
Теперь я вижу ответ Дэниела и согласен с ним, он довольно ограничен.
На мой взгляд, более сильный подход - использовать код Марти Алчина из его книги 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 для каждого объекта истории. Ваш код будет запускаться каждый раз при сохранении записи журнала истории. Док: сигналы Django
источник
Пример кода
Здравствуйте,
Я недавно взломал некоторые журналы для "обновления" для нашей базы данных инвентаризации серверов. Я решил, что поделюсь своим «примером» кода. Следующая функция принимает один из наших объектов «Сервер», список вещей, которые были изменены, и action_flag либо ADDITION, либо CHANGE. Это немного упрощает ситуацию, когда ДОБАВЛЕНИЕ означает «добавлен новый сервер». Более гибкий подход позволит добавить атрибут к серверу. Конечно, было достаточно сложно провести аудит наших существующих функций, чтобы определить, действительно ли произошли изменения, поэтому я достаточно счастлив зарегистрировать новые атрибуты как «изменение».
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."
источник