Skip to content

Commit 40b7974

Browse files
committed
add new example to the format_html page
1 parent bd966ad commit 40b7974

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

content/pages/examples/django/django-utils-html-format-html.markdown

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,97 @@ def djng_locale_script(context, default_language='en'):
158158
language = default_language
159159
~~ return format_html('angular-locale_{}.js', language.lower())
160160
```
161+
162+
163+
## Example 2 from django-auditlog
164+
[Auditlog](https://github.com/jjkester/django-auditlog)
165+
([project documentation](https://django-auditlog.readthedocs.io/en/latest/))
166+
is a [Django](/django.html) app that logs changes to Python objects,
167+
similar to the Django admin's logs but with more details and
168+
output formats.
169+
170+
[**django-auditlog / src / auditlog / mixins.py**](https://github.com/jjkester/django-auditlog/blob/master/src/auditlog/mixins.py)
171+
172+
```python
173+
import json
174+
175+
from django.conf import settings
176+
try:
177+
from django.core import urlresolvers
178+
except ImportError:
179+
from django import urls as urlresolvers
180+
try:
181+
from django.urls.exceptions import NoReverseMatch
182+
except ImportError:
183+
from django.core.urlresolvers import NoReverseMatch
184+
~~from django.utils.html import format_html
185+
from django.utils.safestring import mark_safe
186+
187+
MAX = 75
188+
189+
190+
class LogEntryAdminMixin(object):
191+
192+
def created(self, obj):
193+
return obj.timestamp.strftime('%Y-%m-%d %H:%M:%S')
194+
created.short_description = 'Created'
195+
196+
def user_url(self, obj):
197+
if obj.actor:
198+
app_label, model = settings.AUTH_USER_MODEL.split('.')
199+
viewname = 'admin:%s_%s_change' % (app_label,
200+
model.lower())
201+
try:
202+
link = urlresolvers.reverse(viewname,
203+
args=[obj.actor.id])
204+
except NoReverseMatch:
205+
return u'%s' % (obj.actor)
206+
~~ return format_html(u'<a href="{}">{}</a>',
207+
~~ link, obj.actor)
208+
209+
return 'system'
210+
user_url.short_description = 'User'
211+
212+
def resource_url(self, obj):
213+
app_label, model = obj.content_type.app_label,
214+
obj.content_type.model
215+
viewname = 'admin:%s_%s_change' % (app_label, model)
216+
try:
217+
args = [obj.object_pk] if obj.object_id is \
218+
None else [obj.object_id]
219+
link = urlresolvers.reverse(viewname, args=args)
220+
except NoReverseMatch:
221+
return obj.object_repr
222+
else:
223+
~~ return format_html(u'<a href="{}">{}</a>',
224+
~~ link, obj.object_repr)
225+
resource_url.short_description = 'Resource'
226+
227+
def msg_short(self, obj):
228+
if obj.action == 2:
229+
return '' # delete
230+
changes = json.loads(obj.changes)
231+
s = '' if len(changes) == 1 else 's'
232+
fields = ', '.join(changes.keys())
233+
if len(fields) > MAX:
234+
i = fields.rfind(' ', 0, MAX)
235+
fields = fields[:i] + ' ..'
236+
return '%d change%s: %s' % (len(changes), s, fields)
237+
msg_short.short_description = 'Changes'
238+
239+
def msg(self, obj):
240+
if obj.action == 2:
241+
return '' # delete
242+
changes = json.loads(obj.changes)
243+
msg = '<table><tr><th>#</th><th>Field</th>' + \
244+
'<th>From</th><th>To</th></tr>'
245+
for i, field in enumerate(sorted(changes), 1):
246+
value = [i, field] + (['***', '***'] if field == \
247+
'password' else changes[field])
248+
~~ msg += format_html('<tr><td>{}</td><td>{}</td><td>' + \
249+
~~ '{}</td><td>{}</td></tr>', *value)
250+
251+
msg += '</table>'
252+
return mark_safe(msg)
253+
msg.short_description = 'Changes'
254+
```

0 commit comments

Comments
 (0)