django-fsm-log
raw JSON → 5.0.2 verified Mon Apr 27 auth: no python
A lightweight Django library that logs state transitions for models using django-fsm. Version 5.0.2 supports Django 3.2–5.1, Python 3.9–3.13, and switched to django-fsm-2. Released via Jazzband with monthly patches.
pip install django-fsm-log Common errors
error ImportError: cannot import name 'FSMStateLog' from 'fsm_log.models' ↓
cause The model was renamed from FSMStateLog to StateLog in a previous major version.
fix
Change your import to: 'from fsm_log.models import StateLog'
error ModuleNotFoundError: No module named 'django_fsm' ↓
cause django-fsm-log v4+ depends on django-fsm-2, not django-fsm. The django-fsm package is not installed.
fix
Run 'pip uninstall django-fsm' then 'pip install django-fsm-2', or let django-fsm-log pull it in automatically.
error django.core.management.base.SystemCheckError: ... model 'MyModel' has no attribute 'state' or transition not found ↓
cause The FSMLogMixin may not be properly inheriting or the FSMField is misconfigured.
fix
Ensure FSMLogMixin is listed before models.Model in class definition, and that you have a valid FSMField with 'protected=True'.
Warnings
breaking v4.0.0 switched from django-fsm to django-fsm-2 as a dependency. If you have django-fsm pinned in your requirements, uninstall it and use django-fsm-2 instead. ↓
fix Run 'pip uninstall django-fsm' and ensure django-fsm-2 is installed.
breaking v4.0.0 dropped support for Python 3.7, 3.8 and Django 2.2, 4.0. Upgrade your environment if needed. ↓
fix Use Python >=3.9 and Django >=3.2 (but <5.2 for now).
deprecated The model class used to be called 'FSMStateLog' in versions <3.x. In current versions it is 'StateLog'. ↓
fix Import 'StateLog' from 'fsm_log.models' instead.
gotcha FSMLogMixin must be placed before 'models.Model' in the class inheritance, otherwise the mixin's save method may not get called. ↓
fix Always define your model as 'class MyModel(FSMLogMixin, models.Model):' - mixin first.
gotcha The decorator 'fsm_log_description' must be placed above @transition, not below, otherwise it won't capture the description. ↓
fix Ensure 'fsm_log_description' is on top of 'transition': @fsm_log_description('desc')\n@transition(...)
Imports
- FSMLogMixin
from fsm_log.mixins import FSMLogMixin - StateLog wrong
from fsm_log.models import FSMStateLogcorrectfrom fsm_log.models import StateLog - log_transition wrong
from fsm_log.models import log_transitioncorrectfrom fsm_log.decorators import log_transition
Quickstart
from django.db import models
from django_fsm import FSMField, transition
from fsm_log.mixins import FSMLogMixin
class Article(FSMLogMixin, models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
state = FSMField(default='draft', protected=True)
@transition(field=state, source='draft', target='published')
def publish(self):
pass
# usage
article = Article.objects.create(title='Test', content='...')
article.publish()
article.save()
from fsm_log.models import StateLog
log_entries = StateLog.objects.filter(object_id=article.pk)
print(log_entries.count()) # >0