def session_fields(self): HistoryModel = get_history_model() auto_populated = [ "id", "change_type", "content_type", "object_id", "snapshot", "changes", ] for f in HistoryModel._meta.get_fields(): if f.concrete and f.name not in auto_populated: yield f
def create_trigger(self, model, trigger_type): HistoryModel = get_history_model() ct = ContentType.objects.get_for_model(model) tr_name = self.trigger_name(model, trigger_type) session_cols = [] session_values = [] for field in self.session_fields(): session_cols.append('"' + field.column + '"') session_values.append("history_{}()".format(field.column)) self.drop_trigger(model, trigger_type) fields = list(self.model_fields(model, trigger_type)) if not fields: return tr_name, [] self.execute(""" CREATE TRIGGER {trigger_name} AFTER {action} ON {table} BEGIN INSERT INTO {history_table} ( change_type, content_type_id, object_id, snapshot, changes, {session_cols} ) VALUES ( '{change_type}', {ctid}, {pk_ref}.{pk_col}, {snapshot}, {changes}, {session_values} ); END; """.format( trigger_name=tr_name, action=trigger_type.name, table=model._meta.db_table, history_table=HistoryModel._meta.db_table, change_type=trigger_type.value, ctid=ct.pk, pk_ref=trigger_type.pk_alias, pk_col=model._meta.pk.column, snapshot=self._json_object(fields, trigger_type), changes=self._json_changes(fields, trigger_type), session_cols=", ".join(session_cols), session_values=", ".join(session_values), )) return tr_name, [f.column for f in fields]
def show_history(self, request, queryset, extra_context=None): model_class = queryset.model ct = ContentType.objects.get_for_model(model_class) object_history = (get_history_model().objects.filter( content_type=ct, object_id__in=queryset.values_list( "pk", flat=True)).order_by("session_date")) context = { **self.admin_site.each_context(request), "history": object_history, "title": f"{ model_class.__name__ } History", "opts": model_class._meta, "queryset": queryset, **(extra_context or {}), } request.current_app = self.admin_site.name return TemplateResponse(request, self.history_template, context)
def install(self): HistoryModel = get_history_model() obj_type = HistoryModel._meta.get_field("object_id").db_type(self.conn) session_cols = [] session_values = [] for field in self.session_fields(): session_cols.append(field.column) session_values.append( "nullif(current_setting('history.{field}', true), '')::{type}". format( field=field.name, type=field.rel_db_type(self.conn), )) self.execute( TRIGGER_FUNCTION_SQL.format( table=HistoryModel._meta.db_table, obj_type=obj_type, session_cols=", ".join(session_cols), session_values=", ".join(session_values), ))
from django.contrib import admin from django.contrib.admin.utils import unquote from django.contrib.contenttypes.models import ContentType from django.core.exceptions import PermissionDenied from django.template.response import TemplateResponse from django.utils.translation import gettext_lazy as _ from history import conf, get_history_model from history.templatetags.history import format_json HistoryModel = get_history_model() class HistoryAdminMixin: actions = ["show_history"] history_template = "history/admin_history.html" def show_history(self, request, queryset, extra_context=None): model_class = queryset.model ct = ContentType.objects.get_for_model(model_class) object_history = (get_history_model().objects.filter( content_type=ct, object_id__in=queryset.values_list( "pk", flat=True)).order_by("session_date")) context = { **self.admin_site.each_context(request), "history": object_history, "title": f"{ model_class.__name__ } History", "opts": model_class._meta, "queryset": queryset,
def clear(self): get_history_model().objects.all().delete()
def history(self): return get_history_model().objects.filter(session_id=self.session_id)
def clear(self): HistoryModel = get_history_model() self.execute( "TRUNCATE {table};".format(table=HistoryModel._meta.db_table))