A collection of utilities for admin log entries management.
This module provides functions to add log entries for instance addition, change and deletion, as seen in django.contrib.admin.options. It also provides a class based view mixin to add logging capabilities, and other tools as a log collector.
See docstrings for a better description.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | from django.contrib.admin import models
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext as _
from django.utils.encoding import force_unicode
from django.utils.text import get_text_list
def get_change_message(fields):
"""
Create a change message for *fields* (a sequence of field names).
"""
return _('Changed %s.') % get_text_list(fields, _('and'))
def addition(request, object):
"""
Log that an object has been successfully added.
"""
models.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=models.ADDITION
)
def change(request, object, message_or_fields):
"""
Log that an object has been successfully changed.
The argument *message_or_fields* must be a sequence of modified field names
or a custom change message.
"""
if isinstance(message_or_fields, basestring):
message = message_or_fields
else:
message = get_change_message(message_or_fields)
models.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=models.CHANGE,
change_message=message
)
def deletion(request, object, object_repr=None):
"""
Log that an object will be deleted.
"""
models.LogEntry.objects.log_action(
user_id=request.user.id,
content_type_id=ContentType.objects.get_for_model(object).pk,
object_id=object.pk,
object_repr=object_repr or force_unicode(object),
action_flag=models.DELETION
)
def in_bulk(request, added, changed, deleted):
"""
Log all *added*, *changed* and *deleted* instances.
Note that, while *added* and *deleted* are sequences of instances,
*changed* must be a sequence of tuples *(instance, message_or_fields)*,
where *message_or_fields* is a sequence of modified field names
or a custom change message.
"""
for instance in added:
addition(request, instance)
for instance, fields in changed:
if fields:
change(request, instance, fields)
for instance in deleted:
deletion(request, instance)
class AdminLogMixin(object):
"""
Class based views mixin that adds simple wrappers to
the three functions above.
"""
def log_addition(self, instance):
"""
Log that an object has been successfully added.
"""
addition(self.request, instance)
def log_change(self, instance, message_or_fields):
"""
Log that an object has been successfully changed.
"""
change(self.request, instance, message_or_fields)
def log_deletion(self, instance, instance_repr=None):
"""
Log that an object will be deleted.
"""
deletion(self.request, instance, instance_repr)
def logall(self, added, changed, deleted):
in_bulk(self.request, added, changed, deleted)
class AdminLogger(AdminLogMixin):
"""
A more generic Python object that can be used as a logger
taking the request in the constructor.
"""
def __init__(self, request):
self.request = request
class AdminLogCollector(object):
"""
A class to collect logs that will be reported later.
It can be useful, for example, when you need to add log entries
in forms (e.g. in a custom admin page) without the need to pass a
request argument::
class MyForm(forms.Form):
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.collector = AdminLogCollector()
def save(self):
... add some instance
self.collector.added(instance)
If you have a formset of forms like the above, it is easy to
collect all logs::
class MyBaseFormSet(BaseFormSet):
def save(self):
collectors = []
for form in self.forms:
form.save()
collectors.append(form.collector)
# collect changes for all forms
self.collector = sum(collectors, AdminLogCollector())
# return the number of forms that did something
return len(filter(None, collectors))
In the view you can actually save all collected log entries::
formset.collector.logall(request)
"""
def __init__(self, added=None, changed=None, deleted=None, logger=None):
self._added = set() if added is None else set(added)
self._changed = set() if changed is None else set(changed)
self._deleted = set() if deleted is None else set(deleted)
self._logger = logger or in_bulk
self._done = False
def __add__(self, other):
added, changed, deleted = other.get_collected()
return self.__class__(
self._added.union(added),
self._changed.union(changed),
self._deleted.union(deleted),
logger=self._logger
)
def __repr__(self):
return repr(self.get_collected())
def __nonzero__(self):
return any(self.get_collected())
def added(self, instance):
"""
Collect an addition log.
"""
self._added.add(instance)
def changed(self, instance, message_or_fields):
"""
Collect a change log.
"""
if not isinstance(message_or_fields, basestring):
message_or_fields = tuple(message_or_fields)
self._changed.add((instance, message_or_fields))
def deleted(self, instance):
"""
Collect a deletion log.
"""
self._deleted.add(instance)
def get_collected(self):
"""
Return a tuple *(additions, changes, deletions)*
representing all the collected logs.
"""
return self._added, self._changed, self._deleted
def logall(self, request, redo=False):
"""
Actually save all log entries using the given *request*.
"""
if redo or not self._done:
self._logger(request, self._added, self._changed, self._deleted)
self._done = True
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 9 months, 4 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months ago
- Serializer factory with Django Rest Framework by julio 1 year, 4 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 5 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Please login first before commenting.