Skip to main content

Django Finite State Machine Log

test suite codecov pre-commit.ci status Documentation Status

Provides persistence of the transitions of your fsm's models. Backed by the excellent Django FSM 2 package.

Logs can be accessed before a transition occurs and before they are persisted to the database by enabling a cached backend. See Advanced Usage

Compatibility

  • python 3.11+
  • django 5.2+
  • django-fsm-2

Installation

First, install the package with pip. This will automatically install any dependencies you may be missing

pip install django-fsm-log

Register django_fsm_log in your list of Django applications:

INSTALLED_APPS = (
    ...,
    "django_fsm_log",
    ...,
)

Then migrate the app to create the database table

python manage.py migrate django_fsm_log

Usage

The app listens for the django_fsm.signals.post_transition signal and creates a new record for each transition.

To query the log:

from django_fsm_log.models import StateLog

StateLog.objects.all()
# ...all recorded logs...

Disabling logging for specific models

By default transitions get recorded for all models. Logging can be disabled for specific models by adding their fully qualified name to DJANGO_FSM_LOG_IGNORED_MODELS.

DJANGO_FSM_LOG_IGNORED_MODELS = ("poll.models.Vote",)

for_ Manager Method

For convenience there is a custom for_ manager method to easily filter on the generic foreign key:

from my_app.models import Article
from django_fsm_log.models import StateLog

article = Article.objects.all()[0]

StateLog.objects.for_(article)
# ...logs for article...

by Decorator

We found that our transitions are commonly called by a user, so we've added a decorator to make logging this easy:

from django.db import models
from django_fsm import FSMField, transition
from django_fsm_log.decorators import fsm_log_by


class Article(models.Model):
    state = FSMField(default="draft", protected=True)

    @fsm_log_by
    @transition(field=state, source="draft", target="submitted")
    def submit(self, by=None):
        pass

With this the transition gets logged when the by kwarg is present.

article = Article.objects.create()
article.submit(by=some_user)  # StateLog.by will be some_user

description Decorator

Decorator that allows to set a custom description (saved on database) to a transitions.

from django.db import models
from django_fsm import FSMField, transition
from django_fsm_log.decorators import fsm_log_description


class Article(models.Model):
    state = FSMField(default="draft", protected=True)

    @fsm_log_description(description="Article submitted")  # description param is NOT required
    @transition(field=state, source="draft", target="submitted")
    def submit(self, description=None):
        pass


article = Article.objects.create()
article.submit()  # logged with "Article submitted" description
article.submit(
    description="Article reviewed and submitted"
)  # logged with "Article reviewed and submitted" description

.. TIP:: The "description" argument passed when calling ".submit" has precedence over the default description set in the decorator

The decorator also accepts a allow_inline boolean argument that allows to set the description inside the transition method.

from django.db import models
from django_fsm import FSMField, transition
from django_fsm_log.decorators import fsm_log_description


class Article(models.Model):
    state = FSMField(default="draft", protected=True)

    @fsm_log_description(allow_inline=True)
    @transition(field=state, source="draft", target="submitted")
    def submit(self, description=None):
        description.set("Article submitted")


article = Article.objects.create()
article.submit()  # logged with "Article submitted" description

Admin integration

There is an InlineForm available that can be used to display the history of changes.

To use it expand your own AdminModel by adding StateLogInline to its inlines:

from django.contrib import admin
from django_fsm_log.admin import StateLogInline


@admin.register(FSMModel)
class FSMModelAdmin(admin.ModelAdmin):
    inlines = [StateLogInline]

Advanced Usage

You can change the behaviour of this app by turning on caching for StateLog records. Simply add DJANGO_FSM_LOG_STORAGE_METHOD = 'django_fsm_log.backends.CachedBackend' to your project's settings file. It will use your project's default cache backend by default. If you wish to use a specific cache backend, you can add to your project's settings:

DJANGO_FSM_LOG_CACHE_BACKEND = "some_other_cache_backend"

The StateLog object is now available after the django_fsm.signals.pre_transition signal is fired, but is deleted from the cache and persisted to the database after django_fsm.signals.post_transition is fired.

This is useful if:

  • you need immediate access to StateLog details, and cannot wait until django_fsm.signals.post_transition has been fired
  • at any stage, you need to verify whether or not the StateLog has been written to the database

Access to the pending StateLog record is available via the pending_objects manager

from django_fsm_log.models import StateLog

article = Article.objects.get(...)
pending_state_log = StateLog.pending_objects.get_for_object(article)

Contributing

Running tests

pip install tox
tox

Linting with pre-commit

We use ruff, black and more, all configured and check via pre-commit. Before committing, run the following:

pip install pre-commit
pre-commit install

Changelog

6.0.0 (2026-11-09)

  • Check django compatibility for versions 5.2, 6.0 and 6.1
  • drop python check compatibility for python 3.10 and add python 3.15 to the test environments.
  • Switched to trusted publisher release process with Django Commons
  • Switch from Jazzband org to Django Commons

5.0.2 ( 2026-01-27 )

  • Try to publish straight to pypi thanks to oicd trusted publishing process

5.0.1 ( ❌ )

  • switch from setuptools to hatchling

5.0.0 ( ❌ )

  • ⚠️ Drop python3.9 support
  • Add python3.14 support
  • Add django 5.2, 6.0 support

4.0.5 ( ❌ )

  • Switch to uv

4.0.4 ( ❌ )

4.0.3 ( ❌ )

4.0.2 ( ❌ )

  • Upgrade pypa/gh-action-pypi-publish as an attempt to fix publication of releases to pypi.

4.0.1 (2025-01-07)

Same as 4.0.0 with a fix on setup.py version

4.0.0 (2025-01-07)

  • ⚠️ remove support for django 2.2 & 4.0
  • ⚠️ remove support for python 3.7 & 3.8
  • add support for django 5.1 and python 3.13
  • Switch to django-fsm-2

Discontinued supported versions will most likely continue to work.

3.1.0 (2023-03-23)

  • fsm_log_description now accepts a default description parameter
  • Document fsm_log_description decorator
  • Add support for Django 4.1
  • Add compatibility for python 3.11

3.0.0 (2022-01-14)

  • Switch to github actions (from travis-ci)
  • Test against django 3.2 and 4.0, then python 3.9 and 3.10
  • Drop support for django 1.11, 2.0, 2.1, 3.0, 3.1
  • Drop support for python 3.4, 3.5, 3.6
  • allow using StateLogManager in migrations #95

2.0.1 (2020-03-26)

  • Add support for django3.0
  • Drop support for python2

1.6.2 (2019-01-06)

  • Address Migration history breakage added in 1.6.1

1.6.1 (2018-12-02)

  • Make StateLog.description field nullable

1.6.0 (2018-11-14)

  • Add source state on transitions
  • Fixed get_state_display with FSMIntegerField (#63)
  • Fixed handling of transitions if target is None (#71)
  • Added fsm_log_description decorator (#1, #67)
  • Dropped support for Django 1.10 (#64)

1.5.0 (2017-11-29)

  • cleanup deprecated code.
  • add codecov support.
  • switch to pytest.
  • add Admin integration to visualize past transitions.

1.4.0 (2017-11-09)

  • Bring compatibility with Django 2.0 and drop support of unsupported versions of Django: 1.6, 1.7, 1.9.

Metadata

Release files for django-fsm-log 6.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-fsm-log 6.0.0
File Size Uploaded Provenance Actions
django_fsm_log-6.0.0.tar.gz 9.2 kB With provenance Details for django_fsm_log-6.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for django-fsm-log 6.0.0
File Interpreter ABI Platform Actions
django_fsm_log-6.0.0-py3-none-any.whl Python 3 none any Details for django_fsm_log-6.0.0-py3-none-any.whl

Total release size: 23.2 kB

Release files / django_fsm_log-6.0.0.tar.gz

Download URL django_fsm_log-6.0.0.tar.gz
Size 9.2 kB
Tags Source
SHA-256 checksum
How to use checksums
eb6511da626c1d2c8aab26ed2fab987386e2975fe30cf61104d0ff6172ed78db
BLAKE2b-256 checksum
How to use checksums
76cf30c4fc40252f74a09cbffc1afd3349908da5b11b7f122ae1642d65f3e9bf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.

Transparency log

Release files / django_fsm_log-6.0.0-py3-none-any.whl

Download URL django_fsm_log-6.0.0-py3-none-any.whl
Size 14.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4057f99bad17a96dd6dbbdba7184080b7c95ac67e0f6f3e1607cea9521f22137
BLAKE2b-256 checksum
How to use checksums
84f50764d7dd6ca9dc4de784c536b3f3d2ddabeaa789f96ce1416c86b1fba3c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.

Transparency log

Security for django-fsm-log 6.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for django_fsm_log-6.0.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page