Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,6 @@ test.db

# django fsm command tests
exports/*

# codex
.codex/*
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,11 @@ repos:
hooks:
- id: ruff-format
- id: ruff-check

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.19.1
hooks:
- id: mypy
additional_dependencies:
- django-stubs==5.2.9
- django-guardian
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Changelog
=========

UNRELEASED
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- Add typing
- Add logging solution


django-fsm-2 4.1.0 2025-11-03
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
40 changes: 39 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,45 @@ executed transitions, make sure:
Following these recommendations, `ConcurrentTransitionMixin` will cause a
rollback of all changes executed in an inconsistent state.

## Transition tracking

Use `@django_fsm.track()` to write state changes to a log table.
By default, it writes to `django_fsm.StateLog` (single table).
If you prefer one table per model, define your own log model and pass it in.
You can also capture `author` and `description` for each transition.

```python
import django_fsm
from django_fsm.log import fsm_log_by
from django_fsm.log import fsm_log_description
from django.db import models


@django_fsm.track()
class BlogPost(models.Model):
state = django_fsm.FSMField(default="new")

@fsm_log_by
@fsm_log_description
@django_fsm.transition(field=state, source="new", target="published")
def publish(self):
pass
```

```python
import django_fsm
from django.db import models


class BlogPostLog(django_fsm.TransitionLogBase):
post = models.ForeignKey("BlogPost", on_delete=models.CASCADE, related_name="transition_logs")


@django_fsm.track(log_model=BlogPostLog, relation_field="post")
class BlogPost(models.Model):
state = django_fsm.FSMField(default="new")
```

## Drawing transitions

Render a graphical overview of your model transitions.
Expand Down Expand Up @@ -460,7 +499,6 @@ INSTALLED_APPS = (
## Extensions

- Admin integration: <https://github.com/coral-li/django-fsm-2-admin>
- Transition logging: <https://github.com/gizmag/django-fsm-log>

## Contributing

Expand Down
Loading