0
# Django FSM
1
2
Django FSM provides declarative finite state machine support for Django models through FSMField and the @transition decorator. It enables developers to manage model state transitions in a structured way by decorating methods that can contain side-effects of state changes, supports conditional transitions with permission checking, optimistic locking to prevent concurrent state modifications, and state-based proxy model switching.
3
4
## Package Information
5
6
- **Package Name**: django-fsm
7
- **Language**: Python
8
- **Installation**: `pip install django-fsm`
9
10
## Core Imports
11
12
```python
13
from django_fsm import FSMField, transition
14
```
15
16
Common additional imports:
17
18
```python
19
from django_fsm import (
20
FSMField, FSMIntegerField, FSMKeyField,
21
transition, can_proceed, has_transition_perm,
22
TransitionNotAllowed, ConcurrentTransition, InvalidResultState,
23
FSMModelMixin, ConcurrentTransitionMixin,
24
GET_STATE, RETURN_VALUE
25
)
26
```
27
28
For signals:
29
30
```python
31
from django_fsm.signals import pre_transition, post_transition
32
```
33
34
## Basic Usage
35
36
```python
37
from django.db import models
38
from django_fsm import FSMField, transition
39
40
class BlogPost(models.Model):
41
state = FSMField(default='new')
42
title = models.CharField(max_length=200)
43
content = models.TextField()
44
45
@transition(field=state, source='new', target='published')
46
def publish(self):
47
"""
48
This method may contain side-effects like
49
updating caches, notifying users, etc.
50
"""
51
pass
52
53
@transition(field=state, source='published', target='archived')
54
def archive(self):
55
pass
56
57
# Usage example
58
blog_post = BlogPost.objects.create(title="My Post", content="Content")
59
print(blog_post.state) # 'new'
60
61
blog_post.publish()
62
blog_post.save()
63
print(blog_post.state) # 'published'
64
65
# Check if transition is possible before calling
66
from django_fsm import can_proceed
67
68
if can_proceed(blog_post.archive):
69
blog_post.archive()
70
blog_post.save()
71
```
72
73
## Architecture
74
75
Django FSM uses a decorator-based approach to define state machines:
76
77
- **FSM Fields**: Special Django model fields that store state and provide transition management
78
- **Transition Decorator**: Marks methods as state transitions with source/target configuration
79
- **Meta Information**: Internal tracking of transitions, conditions, and permissions
80
- **Signal System**: Hooks for pre/post transition events
81
- **Optimistic Locking**: Protection against concurrent state modifications
82
83
The library integrates seamlessly with Django's ORM and provides dynamic methods for each FSM field to query available transitions.
84
85
## Capabilities
86
87
### Field Types and Configuration
88
89
Core FSM field types for different data storage needs: CharField-based FSMField, IntegerField-based FSMIntegerField, and ForeignKey-based FSMKeyField. Includes configuration options for default states, protection against direct modification, and state-based proxy model switching.
90
91
```python { .api }
92
class FSMField(FSMFieldMixin, models.CharField):
93
def __init__(self, default=None, protected=False, state_choices=None, max_length=50, **kwargs): ...
94
95
class FSMIntegerField(FSMFieldMixin, models.IntegerField):
96
def __init__(self, default=None, protected=False, state_choices=None, **kwargs): ...
97
98
class FSMKeyField(FSMFieldMixin, models.ForeignKey):
99
def __init__(self, to, default=None, protected=False, state_choices=None, **kwargs): ...
100
```
101
102
[Field Types](./field-types.md)
103
104
### Transition Management
105
106
Decorator for marking methods as state transitions with comprehensive configuration options including source/target states, error handling, conditions, permissions, and custom metadata. Also includes utility functions to check transition availability and permissions.
107
108
```python { .api }
109
def transition(field, source="*", target=None, on_error=None, conditions=[], permission=None, custom={}): ...
110
111
def can_proceed(bound_method, check_conditions=True): ...
112
113
def has_transition_perm(bound_method, user): ...
114
```
115
116
[Transitions](./transitions.md)
117
118
### Model Mixins and Advanced Features
119
120
Model mixins for enhanced FSM functionality including refresh_from_db support for protected fields and optimistic locking protection against concurrent transitions. These mixins provide additional safety and reliability features for production applications.
121
122
```python { .api }
123
class FSMModelMixin(object):
124
def refresh_from_db(self, *args, **kwargs): ...
125
126
class ConcurrentTransitionMixin(object):
127
def save(self, *args, **kwargs): ...
128
```
129
130
[Model Mixins](./model-mixins.md)
131
132
### Exception Handling
133
134
Exception classes for managing state transition errors including general transition failures, concurrent modification conflicts, and invalid result states. Proper exception handling is essential for robust state machine implementations.
135
136
```python { .api }
137
class TransitionNotAllowed(Exception):
138
def __init__(self, *args, object=None, method=None, **kwargs): ...
139
140
class ConcurrentTransition(Exception): ...
141
142
class InvalidResultState(Exception): ...
143
```
144
145
[Exception Handling](./exceptions.md)
146
147
### Signal System and Events
148
149
Django signals for hooking into state transition lifecycle events, enabling custom logic before and after transitions. Signals provide a clean way to implement cross-cutting concerns like logging, notifications, and audit trails.
150
151
```python { .api }
152
# From django_fsm.signals
153
pre_transition = Signal()
154
post_transition = Signal()
155
```
156
157
[Signals](./signals.md)
158
159
### Dynamic State Classes
160
161
Classes for dynamic state resolution allowing transition targets to be determined at runtime based on method return values or custom functions. This enables flexible state machines that can adapt to different business logic scenarios.
162
163
```python { .api }
164
class RETURN_VALUE(State):
165
def __init__(self, *allowed_states): ...
166
167
class GET_STATE(State):
168
def __init__(self, func, states=None): ...
169
```
170
171
[Dynamic States](./dynamic-states.md)
172
173
### Visualization and Management
174
175
Django management command for creating GraphViz visualizations of state machine transitions, helping developers understand and document complex state workflows. The command generates dot files that can be rendered as images or interactive graphs.
176
177
```python { .api }
178
# Management command
179
python manage.py graph_transitions [appname[.model[.field]]] --output file.png --layout dot
180
```
181
182
[Visualization](./visualization.md)