Basics¶
Here we briefly overview some of the concepts of django-pghistory
that
are useful to understand to make reading the docs and using the tool easier.
Triggers¶
Postgres triggers are used to reliably store relevant historical changes.
A trigger is a function executed in the database when tables operations like inserts or updates happen.
Triggers aren’t natively supported by Django, so django-pghistory
uses
django-pgtrigger to
register and install triggers.
Although it’s not required to understand how triggers work to use django-pghistory
, we recommend
reading the basics section of the django-pgtrigger docs
for an overview of django-pgtrigger
and Postgres triggers in general.
Here are the main concepts to understand about triggers:
Like indices, triggers are installed in migrations and are attached to database tables.
Triggers can be configred to run based on insert, update, and delete operations on a table.
Triggers have access to copies of the rows being modified, known as the old and new rows.
Triggers can be conditionally executed based on the properites of the modified rows.
Trackers¶
django-pghistory
provides trackers to track historical changes. Trackers are an abstraction on top
of triggers. For example, pghistory.Snapshot
will install a trigger for inserts
and another for updates, ensuring all versions of models are stored when they change.
There are several other trackers that we’ll go over later for more advanced use cases:
pghistory.AfterInsert
, pghistory.AfterUpdate
, pghistory.BeforeUpdate
, pghistory.AfterInsertOrUpdate
,
and pghistory.BeforeDelete
. These trackers, like pghistory.Snapshot
, are simply installing triggers
for pre-defined database operations.
Events¶
An event is a historical record stored by trackers. For example,
the pghistory.Snapshot
tracker stores snapshot events.
Event models mirror the tracked model and add a few additional tracking fields, all of which
are configurable.
Let’s revisit the quickstart example model:
@pghistory.track(pghistory.Snapshot())
class TrackedModel(models.Model):
int_field = models.IntegerField()
text_field = models.TextField()
This generates an event model named TrackedModelEvent
that has every field from
TrackedModel
plus some additional pgh_*
-labeled fields.
The additional fields help distinguish events, reference the tracked
object, and supply additional tracked context. We’ll cover these fields in more detail later.
Context¶
Event models can have free-form context attached to them using the pghistory.context
context manager and decorator.
For example:
with pghistory.context(user_id=1):
# Do changes
Every event will now point to the same context entry, which contains a JSON field with user: 1
in it. Context tracking
is implemented by propagating local Postgres variables in the executed SQL, meaning no additional queries happen
when storing context from your application.
Context tracking allows for rich metadata to be attached to events. The django-pghistory
middleware automatically attaches the authenticated user and URL of the request, and it’s easy to sprinkle in
pghistory.context
when needed in your application.