Django Chronicle is an implementation of the slowly changing dimensions type 4 which uses database triggers.
How to use?
-
Create a custom revision model. e.g.
from chronicle.models import AbstractRevision class Revision(AbstractRevision): user = models.ForeignKey(settings.AUTH_USER_MODEL) created = models.DateTimeField(auto_now_add=True)
-
Set
settings.REVISION_MODELto point to your revision model. e.g.REVISION_MODEL = 'revision.Revision'
-
Let your models inherit from
HistoryMixine.g.from chronicle.models import HistoryMixin from django.db import models class Food(HistoryMixin, models.Model): name = models.CharField(max_length=50)
-
Create all the migrations and run them:
$ manage.py makemigrations $ manage.py migrate
That should create all the
_historytables for your models that inherit from theHistoryMixin. -
Create the database triggers
$ manage.py create_history_triggers
Now every change to your models should be logged in the _history tables
and you can access the model history via the History model which becomes
a field of the original class.
Example usage:
# create
food = Food('Carot')
food.save()
assert(Food.History.objects.filter(id=food.id).count() == 1)
# update
food.name = 'Carrot'
food.save()
assert(Food.History.objects.filter(id=food.id).count() == 2)
# delete
food.delete()
assert(Food.History.objects.filter(id=food.id).count() == 3)
Why database triggers?
The obvious choice to implement model history would be to connect a signal
handler to the post_save and post_delete signal. This has some rather huge
downsides:
1.) QuerySet.update() and a lot of other QuerySet methods do not emit any
signals. Having to limit the code to only use save() can be a rather huge
performance problem depending on the type of application.
2.) There is a rather large performance impact when creating the history via
the Django ORM. A single QuerySet.update() call could result in hundreds
or thousands of inserts. While this could mostly be solved using the
Manager.bulk_create method a database trigger is a lot faster as there is no
extra database roundtrip required.
3.) This works for any kind of raw query - even outside of the Django ORM - as
long as the chronicle.revision_id session variable is properly set.
The only real downside is the DB compatibility. Right now this package only supports the PostgreSQL database engine.
How to issue queries without the Django ORM?
Create a revision by inserting a row into the revision table and set the
chronicle.revision_id session variable like so:
SET chronicle.revision_id = 42; -- replace 42 by the actual revision id
Once you have made all changes to your models don't forget to reset the session variable. Otherwise you might reuse the same revision by accident in the same DB session:
SET chronicle.revision_id TO DEFAULT;
Release files for django-chronicle 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| django_chronicle-0.2.0.tar.gz | 12.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_chronicle-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 23.4 kB
Release files / django_chronicle-0.2.0.tar.gz
| Download URL | django_chronicle-0.2.0.tar.gz |
|---|---|
| Size | 12.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
05d8370741493d01587ef6384844c4fecccb13f91079385b07d6453c0ec11dd1
|
|
BLAKE2b-256 checksum How to use checksums |
ec120ec9869d45ef988aaa4f678b1ef251f6310c8c6103cee8fae1cb201561f1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.7.1 CPython/3.10.12 Linux/5.15.0-97-generic
|
Release files / django_chronicle-0.2.0-py3-none-any.whl
| Download URL | django_chronicle-0.2.0-py3-none-any.whl |
|---|---|
| Size | 10.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8b1cab138e7cc1e148d246a80f278650af26dcff93feedee78cb08342954c1f9
|
|
BLAKE2b-256 checksum How to use checksums |
f2dd3369a8aeb927132fea0cc00c4eae893748de282189f3ff0c9d3d8025df96
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.7.1 CPython/3.10.12 Linux/5.15.0-97-generic
|