diff --git a/core/middleware.py b/core/middleware.py new file mode 100644 index 00000000..c453236b --- /dev/null +++ b/core/middleware.py @@ -0,0 +1,14 @@ +import pghistory + +def setup_pghistory_context(): + """ + Set up pghistory context middleware to track request information. + This function configures what contextual information is stored + with each history record. + """ + pghistory.context(lambda request: { + 'user': str(request.user) if request.user.is_authenticated else None, + 'ip': request.META.get('REMOTE_ADDR'), + 'user_agent': request.META.get('HTTP_USER_AGENT'), + 'session_key': request.session.session_key + }) \ No newline at end of file diff --git a/core/models.py b/core/models.py index 0392ad6a..a717d3e2 100644 --- a/core/models.py +++ b/core/models.py @@ -2,6 +2,18 @@ from django.db import models from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.utils.text import slugify +import pghistory + +@pghistory.track() +class HistoricalModel(models.Model): + """ + Abstract base model that provides universal history tracking via django-pghistory. + """ + class Meta: + abstract = True + + def save(self, *args, **kwargs): + return super().save(*args, **kwargs) class SlugHistory(models.Model): """ @@ -26,9 +38,11 @@ class SlugHistory(models.Model): def __str__(self): return f"Old slug '{self.old_slug}' for {self.content_object}" -class SluggedModel(models.Model): +@pghistory.track() +class SluggedModel(HistoricalModel): """ Abstract base model that provides slug functionality with history tracking. + Inherits from HistoricalModel to get universal history tracking. """ name = models.CharField(max_length=200) slug = models.SlugField(max_length=200, unique=True) @@ -55,6 +69,7 @@ class SluggedModel(models.Model): if not self.slug: self.slug = slugify(self.name) + # Call HistoricalModel's save to ensure history tracking super().save(*args, **kwargs) def get_id_field_name(self): diff --git a/history/apps.py b/history/apps.py new file mode 100644 index 00000000..95bc91d8 --- /dev/null +++ b/history/apps.py @@ -0,0 +1,12 @@ +from django.apps import AppConfig + +class HistoryConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'history' + verbose_name = 'History Tracking' + + def ready(self): + """Initialize app and signal handlers""" + from django.dispatch import Signal + # Create a signal for history updates + self.history_updated = Signal() \ No newline at end of file diff --git a/history/templates/history/partials/history_timeline.html b/history/templates/history/partials/history_timeline.html new file mode 100644 index 00000000..541fcac2 --- /dev/null +++ b/history/templates/history/partials/history_timeline.html @@ -0,0 +1,29 @@ +
{{ event.pgh_data|pprint }}
+ | {key} | {value} |
|---|