mirror of
https://github.com/jazzband/django-auditlog.git
synced 2026-03-16 22:20:26 +00:00
Added verbose field name in admin (#428)
Co-authored-by: Hasan Ramezani <hasan.r67@gmail.com>
This commit is contained in:
parent
fb90112c50
commit
d74c118834
3 changed files with 57 additions and 9 deletions
|
|
@ -3,6 +3,7 @@
|
|||
#### Improvements
|
||||
|
||||
- feat: Add `serialized_data` field on `LogEntry` model. ([#412](https://github.com/jazzband/django-auditlog/pull/412))
|
||||
- feat: Display the field name as it would be displayed in Django Admin or use `mapping_field` if available [#428](https://github.com/jazzband/django-auditlog/pull/428)
|
||||
|
||||
#### Fixes
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,15 @@ import json
|
|||
|
||||
from django import urls as urlresolvers
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import FieldDoesNotExist
|
||||
from django.forms.utils import pretty_name
|
||||
from django.urls.exceptions import NoReverseMatch
|
||||
from django.utils.html import format_html, format_html_join
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.timezone import localtime
|
||||
|
||||
from auditlog.models import LogEntry
|
||||
from auditlog.registry import auditlog
|
||||
|
||||
MAX = 75
|
||||
|
||||
|
|
@ -81,7 +84,9 @@ class LogEntryAdminMixin:
|
|||
msg.append("<table>")
|
||||
msg.append(self._format_header("#", "Field", "From", "To"))
|
||||
for i, (field, change) in enumerate(sorted(atom_changes.items()), 1):
|
||||
value = [i, field] + (["***", "***"] if field == "password" else change)
|
||||
value = [i, self.field_verbose_name(obj, field)] + (
|
||||
["***", "***"] if field == "password" else change
|
||||
)
|
||||
msg.append(self._format_line(*value))
|
||||
msg.append("</table>")
|
||||
|
||||
|
|
@ -99,7 +104,7 @@ class LogEntryAdminMixin:
|
|||
format_html(
|
||||
"<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>",
|
||||
i,
|
||||
field,
|
||||
self.field_verbose_name(obj, field),
|
||||
change["operation"],
|
||||
change_html,
|
||||
)
|
||||
|
|
@ -120,3 +125,19 @@ class LogEntryAdminMixin:
|
|||
return format_html(
|
||||
"".join(["<tr>", "<td>{}</td>" * len(values), "</tr>"]), *values
|
||||
)
|
||||
|
||||
def field_verbose_name(self, obj, field_name: str):
|
||||
model = obj.content_type.model_class()
|
||||
try:
|
||||
model_fields = auditlog.get_model_fields(model._meta.model)
|
||||
mapping_field_name = model_fields["mapping_fields"].get(field_name)
|
||||
if mapping_field_name:
|
||||
return mapping_field_name
|
||||
except KeyError:
|
||||
# Model definition in auditlog was probably removed
|
||||
pass
|
||||
try:
|
||||
field = model._meta.get_field(field_name)
|
||||
return pretty_name(getattr(field, "verbose_name", field_name))
|
||||
except FieldDoesNotExist:
|
||||
return pretty_name(field_name)
|
||||
|
|
|
|||
|
|
@ -1323,8 +1323,8 @@ class DiffMsgTest(TestCase):
|
|||
(
|
||||
"<table>"
|
||||
"<tr><th>#</th><th>Field</th><th>From</th><th>To</th></tr>"
|
||||
"<tr><td>1</td><td>field one</td><td>value before deletion</td><td>None</td></tr>"
|
||||
"<tr><td>2</td><td>field two</td><td>11</td><td>None</td></tr>"
|
||||
"<tr><td>1</td><td>Field one</td><td>value before deletion</td><td>None</td></tr>"
|
||||
"<tr><td>2</td><td>Field two</td><td>11</td><td>None</td></tr>"
|
||||
"</table>"
|
||||
),
|
||||
)
|
||||
|
|
@ -1346,8 +1346,8 @@ class DiffMsgTest(TestCase):
|
|||
(
|
||||
"<table>"
|
||||
"<tr><th>#</th><th>Field</th><th>From</th><th>To</th></tr>"
|
||||
"<tr><td>1</td><td>field one</td><td>None</td><td>a value</td></tr>"
|
||||
"<tr><td>2</td><td>field two</td><td>None</td><td>11</td></tr>"
|
||||
"<tr><td>1</td><td>Field one</td><td>None</td><td>a value</td></tr>"
|
||||
"<tr><td>2</td><td>Field two</td><td>None</td><td>11</td></tr>"
|
||||
"</table>"
|
||||
),
|
||||
)
|
||||
|
|
@ -1369,9 +1369,9 @@ class DiffMsgTest(TestCase):
|
|||
(
|
||||
"<table>"
|
||||
"<tr><th>#</th><th>Field</th><th>From</th><th>To</th></tr>"
|
||||
"<tr><td>1</td><td>field one</td><td>old value of field one</td>"
|
||||
"<tr><td>1</td><td>Field one</td><td>old value of field one</td>"
|
||||
"<td>new value of field one</td></tr>"
|
||||
"<tr><td>2</td><td>field two</td><td>11</td><td>42</td></tr>"
|
||||
"<tr><td>2</td><td>Field two</td><td>11</td><td>42</td></tr>"
|
||||
"</table>"
|
||||
),
|
||||
)
|
||||
|
|
@ -1394,12 +1394,38 @@ class DiffMsgTest(TestCase):
|
|||
(
|
||||
"<table>"
|
||||
"<tr><th>#</th><th>Relationship</th><th>Action</th><th>Objects</th></tr>"
|
||||
"<tr><td>1</td><td>some_m2m_field</td><td>add</td><td>Example User (user 1)"
|
||||
"<tr><td>1</td><td>Some m2m field</td><td>add</td><td>Example User (user 1)"
|
||||
"<br>Illustration (user 42)</td></tr>"
|
||||
"</table>"
|
||||
),
|
||||
)
|
||||
|
||||
def test_unregister_after_log(self):
|
||||
log_entry = self._create_log_entry(
|
||||
LogEntry.Action.CREATE,
|
||||
{
|
||||
"field two": [None, 11],
|
||||
"field one": [None, "a value"],
|
||||
},
|
||||
)
|
||||
# Unregister
|
||||
auditlog.unregister(SimpleModel)
|
||||
self.assertEqual(
|
||||
self.admin.msg_short(log_entry), "2 changes: field two, field one"
|
||||
)
|
||||
self.assertEqual(
|
||||
self.admin.msg(log_entry),
|
||||
(
|
||||
"<table>"
|
||||
"<tr><th>#</th><th>Field</th><th>From</th><th>To</th></tr>"
|
||||
"<tr><td>1</td><td>Field one</td><td>None</td><td>a value</td></tr>"
|
||||
"<tr><td>2</td><td>Field two</td><td>None</td><td>11</td></tr>"
|
||||
"</table>"
|
||||
),
|
||||
)
|
||||
# Re-register
|
||||
auditlog.register(SimpleModel)
|
||||
|
||||
|
||||
class NoDeleteHistoryTest(TestCase):
|
||||
def test_delete_related(self):
|
||||
|
|
|
|||
Loading…
Reference in a new issue