Added verbose field name in admin (#428)

Co-authored-by: Hasan Ramezani <hasan.r67@gmail.com>
This commit is contained in:
Mathieu Rampant 2022-09-20 16:07:41 -04:00 committed by GitHub
parent fb90112c50
commit d74c118834
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 9 deletions

View file

@ -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

View file

@ -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)

View file

@ -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):