Django Lifecycle Hooks
This project provides a @hook decorator as well as a base model and mixin to add lifecycle hooks to your Django models. Django's built-in approach to offering lifecycle hooks is Signals. However, my team often finds that Signals introduce unnecessary indirection and are at odds with Django's "fat models" approach.
Django Lifecycle Hooks supports:
- Python 3.8, 3.9, 3.10, 3.11, 3.12, 3.13 and 3.14
- Django 4.2, 5.0, 5.2 and 6.0
In short, you can write model code like this:
from django_lifecycle import LifecycleModel, hook, BEFORE_UPDATE, AFTER_UPDATE
from django_lifecycle.conditions import WhenFieldValueIs, WhenFieldValueWas, WhenFieldHasChanged
class Article(LifecycleModel):
contents = models.TextField()
updated_at = models.DateTimeField(null=True)
status = models.ChoiceField(choices=['draft', 'published'])
editor = models.ForeignKey(AuthUser)
@hook(BEFORE_UPDATE, WhenFieldHasChanged("contents", has_changed=True))
def on_content_change(self):
self.updated_at = timezone.now()
@hook(
AFTER_UPDATE,
condition=(
WhenFieldValueWas("status", value="draft")
& WhenFieldValueIs("status", value="published")
)
)
def on_publish(self):
send_email(self.editor.email, "An article has published!")
Instead of overriding save and __init__ in a clunky way that hurts readability:
# same class and field declarations as above ...
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._orig_contents = self.contents
self._orig_status = self.status
def save(self, *args, **kwargs):
if self.pk is not None and self.contents != self._orig_contents:
self.updated_at = timezone.now()
super().save(*args, **kwargs)
if self.status != self._orig_status:
send_email(self.editor.email, "An article has published!")
Documentation: https://rsinger86.github.io/django-lifecycle
Source Code: https://github.com/rsinger86/django-lifecycle
Changelog
See Changelog
Testing
Tests are found in a simplified Django project in the /tests folder. Install the project requirements and do ./manage.py test to run them.
License
See License.
Release files for django-lifecycle 1.3.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_lifecycle-1.3.0.tar.gz | 12.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_lifecycle-1.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 28.5 kB
Release files / django_lifecycle-1.3.0.tar.gz
| Download URL | django_lifecycle-1.3.0.tar.gz |
|---|---|
| Size | 12.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9e8b6f7105b074b198dfa19424b7ddf94c067cae6a8baba2cdc6120eb79f9120
|
|
BLAKE2b-256 checksum How to use checksums |
a3bd4bb5e6cda63ded99c9f68578f6271f397c44e7fd7e1806227d6dd20432f7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.25
|
Release files / django_lifecycle-1.3.0-py3-none-any.whl
| Download URL | django_lifecycle-1.3.0-py3-none-any.whl |
|---|---|
| Size | 15.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8c706c7c7d157b1df62e825e01c6f2d14a98d9b298217409ee5e015d93fc73e5
|
|
BLAKE2b-256 checksum How to use checksums |
47f258da8e552d6f74019c8c22624411d336a9b930b99705cefed751c5a4a8f2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.25
|