В django Auditlog Create, Update и Delete у меня работает нормально. Для поиска я пытаюсь настроить данный пакет по умолчанию. В этом пакете они упомянуты. Действительными действиями являются: py: attr: Action.CREATE
,: py: attr: Action.UPDATE
и: py: attr: Action.DELETE
. Хотя я пытался, но не смог достичь цели. Здесь я упомянул код ниже
Models.py:
@ python_2_unicode_compatible
класс LogEntry (models.Model):
class Action:
"""
The actions that Auditlog distinguishes: creating, updating and deleting objects. Viewing objects is not logged.
The values of the actions are numeric, a higher integer value means a more intrusive action. This may be useful
in some cases when comparing actions because the ``__lt``, ``__lte``, ``__gt``, ``__gte`` lookup filters can be
used in queries.
The valid actions are :py:attr:`Action.CREATE`, :py:attr:`Action.UPDATE` and :py:attr:`Action.DELETE`.
"""
CREATE = 0
UPDATE = 1
DELETE = 2
choices = (
(CREATE, _("create")),
(UPDATE, _("update")),
(DELETE, _("delete")),
)
content_type = models.ForeignKey(to='contenttypes.ContentType', on_delete=models.CASCADE, related_name='+', verbose_name=_("content type"))
object_pk = models.CharField(db_index=True, max_length=255, verbose_name=_("object pk"))
object_id = models.BigIntegerField(blank=True, db_index=True, null=True, verbose_name=_("object id"))
object_repr = models.TextField(verbose_name=_("object representation"))
action = models.PositiveSmallIntegerField(choices=Action.choices, verbose_name=_("action"))
changes = models.TextField(blank=True, verbose_name=_("change message"))
actor = models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, blank=True, null=True, related_name='+', verbose_name=_("actor"))
# remote_addr = models.GenericIPAddressField(blank=True, null=True, verbose_name=_("remote address"))
timestamp = models.DateTimeField(auto_now_add=True, verbose_name=_("timestamp"))
# additional_data = JSONField(blank=True, null=True, verbose_name=_("additional data"))
objects = LogEntryManager()
class Meta:
get_latest_by = 'timestamp'
ordering = ['-timestamp']
verbose_name = _("log entry")
verbose_name_plural = _("log entries")
def __str__(self):
if self.action == self.Action.CREATE:
fstring = _("Created {repr:s}")
elif self.action == self.Action.UPDATE:
print("updating",self.action)
fstring = _("Updated {repr:s}")
print(fstring)
elif self.action == self.Action.DELETE:
fstring = _("Deleted {repr:s}")
else:
fstring = _("Logged {repr:s}")
return fstring.format(repr=self.object_repr)
@property
def changes_dict(self):
"""
:return: The changes recorded in this log entry as a dictionary object.
"""
try:
return json.loads(self.changes)
except ValueError:
return {}
@property
def changes_str(self, colon=': ', arrow=smart_text(' \u2192 '), separator='; '):
"""
Return the changes recorded in this log entry as a string. The formatting of the string can be customized by
setting alternate values for colon, arrow and separator. If the formatting is still not satisfying, please use
:py:func:`LogEntry.changes_dict` and format the string yourself.
:param colon: The string to place between the field name and the values.
:param arrow: The string to place between each old and new value.
:param separator: The string to place between each field.
:return: A readable string of the changes in this log entry.
"""
substrings = []
for field, values in iteritems(self.changes_dict):
substring = smart_text('{field_name:s}{colon:s}{old:s}{arrow:s}{new:s}').format(
field_name=field,
colon=colon,
old=values[0],
arrow=arrow,
new=values[1],
)
substrings.append(substring)
return separator.join(substrings)
@property
def changes_display_dict(self):
"""
:return: The changes recorded in this log entry intended for display to users as a dictionary object.
"""
# Get the model and model_fields
from auditlog.registry import auditlog
model = self.content_type.model_class()
model_fields = auditlog.get_model_fields(model._meta.model)
changes_display_dict = {}
# grab the changes_dict and iterate through
for field_name, values in iteritems(self.changes_dict):
# try to get the field attribute on the model
try:
field = model._meta.get_field(field_name)
except FieldDoesNotExist:
changes_display_dict[field_name] = values
continue
values_display = []
# handle choices fields and Postgres ArrayField to get human readable version
choices_dict = None
if hasattr(field, 'choices') and len(field.choices) > 0:
choices_dict = dict(field.choices)
if hasattr(field, 'base_field') and getattr(field.base_field, 'choices', False):
choices_dict = dict(field.base_field.choices)
if choices_dict:
for value in values:
try:
value = ast.literal_eval(value)
if type(value) is [].__class__:
values_display.append(', '.join([choices_dict.get(val, 'None') for val in value]))
else:
values_display.append(choices_dict.get(value, 'None'))
except ValueError:
values_display.append(choices_dict.get(value, 'None'))
except:
values_display.append(choices_dict.get(value, 'None'))
else:
try:
field_type = field.get_internal_type()
except AttributeError:
# if the field is a relationship it has no internal type and exclude it
continue
for value in values:
# handle case where field is a datetime, date, or time type
if field_type in ["DateTimeField", "DateField", "TimeField"]:
try:
value = parser.parse(value)
if field_type == "DateField":
value = value.date()
elif field_type == "TimeField":
value = value.time()
elif field_type == "DateTimeField":
value = value.replace(tzinfo=timezone.utc)
value = value.astimezone(gettz(settings.TIME_ZONE))
value = formats.localize(value)
except ValueError:
pass
# check if length is longer than 140 and truncate with ellipsis
if len(value) > 140:
value = "{}...".format(value[:140])
values_display.append(value)
verbose_name = model_fields['mapping_fields'].get(field.name, getattr(field, 'verbose_name', field.name))
changes_display_dict[verbose_name] = values_display
return changes_display_dict
Registry.py:
класс AuditlogModelRegistry (объект):
def __init__(self, create=True, update=True, delete=True, select=True, custom=None):
from auditlog.receivers import log_create, log_update, log_delete, log_select
self._registry = {}
self._signals = {}
if create:
self._signals[post_save] = log_create
if update:
self._signals[pre_save] = log_update
if delete:
self._signals[post_delete] = log_delete
if select:
self._signals[post_delete] = log_select
if custom is not None:
self._signals.update(custom)
Receivers.py:
def log_create (отправитель, экземпляр создан, ** kwargs):
if created:
changes = model_instance_diff(None, instance)
log_entry = LogEntry.objects.log_create(
instance,
action=LogEntry.Action.CREATE,
changes=json.dumps(changes),
)
def log_update (отправитель, экземпляр, ** kwargs):
if instance.pk is not None:
try:
old = sender.objects.get(pk=instance.pk)
except sender.DoesNotExist:
pass
else:
new = instance
changes = model_instance_diff(old, new)
# Log an entry only if there are changes
if changes:
log_entry = LogEntry.objects.log_create(
instance,
action=LogEntry.Action.UPDATE,
changes=json.dumps(changes),
)
def log_delete (отправитель, экземпляр, ** kwargs):
if instance.pk is not None:
changes = model_instance_diff(instance, None)
log_entry = LogEntry.objects.log_create(
instance,
action=LogEntry.Action.DELETE,
changes=json.dumps(changes),
)
Может кто-нибудь помочь мне решить эту проблему. Заранее спасибо.