如何通过Django auditlog包在Auditlog中实现搜索

时间:2019-03-05 14:37:31

标签: django python-3.x vue.js django-rest-framework django-auditlog

在django auditlog中,Create,Update和Delete对我来说工作正常。对于搜索,我尝试自定义给定的默认软件包。在该软件包中,提到了有效的动作::py:attr:Action.CREATE,:py:attr:Action.UPDATE和:py:attr:Action.DELETE。尽管我已经尝试过,但是我无法实现目标。这里我在下面提到了代码

Models.py:

@ python_2_unicode_compatible

Class 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(object)类:

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(发送方,实例,创建的,**假的):

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(发送方,实例,**垃圾):

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(发送方,实例,**垃圾):

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

任何人都可以帮助我解决这个问题。谢谢。

0 个答案:

没有答案