Настройка списка изменений django-auditlog в админке django
Я начал использовать django-auditlog в своем проекте. Я смог успешно вести журнал изменений в моей модели, однако я хочу внести коррективы в то, как журнал аудита отображает список изменений в админке django. Проблема в том, что у меня есть ForeignKey
в модели Task
, у нее определен метод __str__
. Когда я вношу изменения в поле stage
в моей модели Task
, запись регистрируется, но она показывает этап id
, а не stage.name
, как определено в __str__
(я полагаю, что так и должно работать.
Вот моя models.py
class Stage(models.Model):
name = models.CharField(max_length=64)
def __str__(self):
return self.name
class Task(models.Model):
name = models.CharField(max_length=64)
stage = models.ForeignKey(Stage, on_delete=models.SET_NULL, null=True)
## other unrelated fields...
def __str__(self):
return self.name
Вот как отображается Log Entry
в настоящее время:
Я прочитал документацию по django-auditlog, но не смог найти никакого решения. Что-нибудь посоветуете?
Я смог решить проблему, переопределив LogEntryAdminMixin
class.
Вот что я сделал, чтобы решить проблему:
- Создал
mixins.py
файл в папкеapp
со следующим содержимым:
from auditlog.mixins import LogEntryAdminMixin
from django.contrib import admin
from django.utils.translation import gettext_lazy as _
from django.utils.safestring import mark_safe
import backend.api.models
class CustomLogEntryAdminMixin(LogEntryAdminMixin):
@admin.display(description=_("Changes"))
def msg(self, obj):
changes = obj.changes_dict
atom_changes = {}
m2m_changes = {}
for field, change in changes.items():
if isinstance(change, dict):
assert (
change["type"] == "m2m"
), "Only m2m operations are expected to produce dict changes now"
m2m_changes[field] = change
else:
atom_changes[field] = change
msg = []
if atom_changes:
## this is the part we are overriding
## This is the only change from the original code
## Change stage ids to stage names if obj is a Buy object
if obj.content_type.model == "buy" and "stage" in atom_changes:
atom_changes["stage"] = [
backend.api.models.Stage.objects.get(id=stage_id).name
for stage_id in atom_changes["stage"]
]
msg.append("<table>")
msg.append(self._format_header("#", "Field", "From", "To"))
for i, (field, change) in enumerate(sorted(atom_changes.items()), 1):
value = [i, self.field_verbose_name(obj, field)] + (
["***", "***"] if field == "password" else change
)
msg.append(self._format_line(*value))
msg.append("</table>")
if m2m_changes:
msg.append("<table>")
msg.append(self._format_header("#", "Relationship", "Action", "Objects"))
for i, (field, change) in enumerate(sorted(m2m_changes.items()), 1):
change_html = format_html_join(
mark_safe("<br>"),
"{}",
[(value,) for value in change["objects"]],
)
msg.append(
format_html(
"<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>",
i,
self.field_verbose_name(obj, field),
change["operation"],
change_html,
)
)
msg.append("</table>")
return mark_safe("".join(msg))
- Создал класс Admin в моем приложении
admin.py
для использования этого миксина:
from auditlog.admin import LogEntryAdmin
from auditlog.models import LogEntry
class CustomLogEnterAdmin(LogEntryAdmin, backend.api.mixins.CustomLogEntryAdminMixin):
"""
This class is a custom LogEntryAdmin that extends the default LogEntryAdmin
and uses custom mixins to customize the display of the changes field in the DAP for Buy objects stage field.
"""
pass
- Снимите с регистрации класс по умолчанию
LogEntry
и зарегистрируйте классCustomLogEntryAdmin
, который я только что создал.
# unregister the default LogEntryAdmin and register the custom one
admin.site.unregister(LogEntry)
## register custom log entry admin
admin.site.register(LogEntry, CustomLogEnterAdmin)
Теперь он показывает ForeignKey
значение модели, вместо ключей.
Надеюсь, это поможет!