0
# Field Types and Configuration
1
2
Core FSM field types for different data storage needs and configuration options for controlling state machine behavior.
3
4
## Capabilities
5
6
### FSMField
7
8
CharField-based finite state machine field that stores states as string values. This is the most commonly used FSM field type, suitable for human-readable state names.
9
10
```python { .api }
11
class FSMField(FSMFieldMixin, models.CharField):
12
def __init__(self,
13
default=None,
14
protected=False,
15
state_choices=None,
16
max_length=50,
17
**kwargs):
18
"""
19
State machine field based on CharField.
20
21
Parameters:
22
- default: Default state value
23
- protected: If True, prevents direct field modification
24
- state_choices: List of (state, title, proxy_cls_ref) tuples for proxy switching
25
- max_length: Maximum length for state string (default: 50)
26
- **kwargs: Standard CharField parameters
27
"""
28
```
29
30
Usage example:
31
32
```python
33
from django.db import models
34
from django_fsm import FSMField, transition
35
36
class Order(models.Model):
37
status = FSMField(default='pending', protected=True)
38
39
@transition(field=status, source='pending', target='confirmed')
40
def confirm(self):
41
pass
42
```
43
44
### FSMIntegerField
45
46
IntegerField-based finite state machine field that stores states as integer values. Useful when states need to be represented numerically or when integrating with systems that use integer status codes.
47
48
```python { .api }
49
class FSMIntegerField(FSMFieldMixin, models.IntegerField):
50
def __init__(self,
51
default=None,
52
protected=False,
53
state_choices=None,
54
**kwargs):
55
"""
56
State machine field based on IntegerField.
57
58
Parameters:
59
- default: Default state value (integer)
60
- protected: If True, prevents direct field modification
61
- state_choices: List of (state, title, proxy_cls_ref) tuples for proxy switching
62
- **kwargs: Standard IntegerField parameters
63
"""
64
```
65
66
Usage example:
67
68
```python
69
class Task(models.Model):
70
STATUS_NEW = 0
71
STATUS_IN_PROGRESS = 1
72
STATUS_COMPLETED = 2
73
74
STATUS_CHOICES = [
75
(STATUS_NEW, 'New'),
76
(STATUS_IN_PROGRESS, 'In Progress'),
77
(STATUS_COMPLETED, 'Completed'),
78
]
79
80
status = FSMIntegerField(
81
default=STATUS_NEW,
82
choices=STATUS_CHOICES
83
)
84
85
@transition(field=status, source=STATUS_NEW, target=STATUS_IN_PROGRESS)
86
def start_work(self):
87
pass
88
```
89
90
### FSMKeyField
91
92
ForeignKey-based finite state machine field that stores states as references to related model instances. Useful when states need to be managed in a separate model with additional metadata.
93
94
```python { .api }
95
class FSMKeyField(FSMFieldMixin, models.ForeignKey):
96
def __init__(self,
97
to,
98
default=None,
99
protected=False,
100
state_choices=None,
101
**kwargs):
102
"""
103
State machine field based on ForeignKey.
104
105
Parameters:
106
- to: Related model class or string reference
107
- default: Default state value (foreign key reference)
108
- protected: If True, prevents direct field modification
109
- state_choices: List of (state, title, proxy_cls_ref) tuples for proxy switching
110
- **kwargs: Standard ForeignKey parameters (on_delete required)
111
"""
112
```
113
114
Usage example:
115
116
```python
117
class WorkflowState(models.Model):
118
name = models.CharField(max_length=50, primary_key=True)
119
description = models.TextField()
120
121
class Document(models.Model):
122
state = FSMKeyField(
123
'WorkflowState',
124
default='draft',
125
on_delete=models.PROTECT
126
)
127
128
@transition(field=state, source='draft', target='review')
129
def submit_for_review(self):
130
pass
131
```
132
133
### FSMFieldMixin
134
135
Base mixin class that provides finite state machine functionality to Django model fields. This is the core implementation used by all FSM field types.
136
137
```python { .api }
138
class FSMFieldMixin(object):
139
def __init__(self,
140
*args,
141
protected=False,
142
state_choices=None,
143
**kwargs):
144
"""
145
Base FSM functionality mixin.
146
147
Parameters:
148
- *args: Positional arguments passed to parent field class
149
- protected: If True, prevents direct field assignment
150
- state_choices: List of (state, title, proxy_cls_ref) tuples
151
- **kwargs: Keyword arguments passed to parent field class
152
"""
153
154
def get_state(self, instance): ...
155
def set_state(self, instance, state): ...
156
def change_state(self, instance, method, *args, **kwargs): ...
157
def get_all_transitions(self, instance_cls): ...
158
```
159
160
## Field Configuration Options
161
162
### Protected Fields
163
164
When `protected=True`, the field cannot be modified directly through assignment. State changes must occur through transition methods.
165
166
```python
167
class BlogPost(models.Model):
168
state = FSMField(default='draft', protected=True)
169
170
# This will raise AttributeError
171
# post.state = 'published' # Error!
172
173
# Must use transition instead
174
@transition(field=state, source='draft', target='published')
175
def publish(self):
176
pass
177
```
178
179
### State Choices with Proxy Models
180
181
The `state_choices` parameter allows automatic proxy model switching based on state values:
182
183
```python
184
class BaseDocument(models.Model):
185
state = FSMField(
186
default='draft',
187
state_choices=[
188
('draft', 'Draft', 'DraftDocument'),
189
('published', 'Published', 'PublishedDocument'),
190
]
191
)
192
193
class DraftDocument(BaseDocument):
194
class Meta:
195
proxy = True
196
197
def edit_content(self):
198
pass
199
200
class PublishedDocument(BaseDocument):
201
class Meta:
202
proxy = True
203
204
def unpublish(self):
205
pass
206
207
# When state changes, instance class automatically switches
208
doc = BaseDocument.objects.create()
209
print(type(doc)) # <class 'BaseDocument'>
210
211
doc.state = 'draft'
212
print(type(doc)) # <class 'DraftDocument'>
213
214
doc.state = 'published'
215
print(type(doc)) # <class 'PublishedDocument'>
216
```
217
218
## Dynamic Model Methods
219
220
For each FSM field named `{field_name}`, django-fsm automatically adds these methods to the model:
221
222
### get_all_{field_name}_transitions
223
224
```python { .api }
225
def get_all_{field_name}_transitions(self):
226
"""
227
Returns all transitions available for the field.
228
229
Returns:
230
Generator of Transition objects
231
"""
232
```
233
234
### get_available_{field_name}_transitions
235
236
```python { .api }
237
def get_available_{field_name}_transitions(self):
238
"""
239
Returns transitions available from current state with conditions met.
240
241
Returns:
242
Generator of Transition objects
243
"""
244
```
245
246
### get_available_user_{field_name}_transitions
247
248
```python { .api }
249
def get_available_user_{field_name}_transitions(self, user):
250
"""
251
Returns available transitions that user has permission to execute.
252
253
Parameters:
254
- user: User instance for permission checking
255
256
Returns:
257
Generator of Transition objects
258
"""
259
```
260
261
Usage example:
262
263
```python
264
# For a field named 'status'
265
order = Order.objects.get(pk=1)
266
267
# Get all possible transitions
268
all_transitions = list(order.get_all_status_transitions())
269
270
# Get currently available transitions
271
available = list(order.get_available_status_transitions())
272
273
# Get transitions available to specific user
274
user_transitions = list(order.get_available_user_status_transitions(request.user))
275
```
276
277
## Utility Functions
278
279
These functions power the dynamic model methods and can be used directly when needed:
280
281
### get_available_FIELD_transitions
282
283
```python { .api }
284
def get_available_FIELD_transitions(instance, field):
285
"""
286
List of transitions available in current model state with all conditions met.
287
288
Parameters:
289
- instance: Model instance
290
- field: FSM field instance
291
292
Returns:
293
Generator yielding Transition objects that are available from current state
294
"""
295
```
296
297
### get_all_FIELD_transitions
298
299
```python { .api }
300
def get_all_FIELD_transitions(instance, field):
301
"""
302
List of all transitions available in current model state.
303
304
Parameters:
305
- instance: Model instance
306
- field: FSM field instance
307
308
Returns:
309
Generator yielding all Transition objects for the field
310
"""
311
```
312
313
### get_available_user_FIELD_transitions
314
315
```python { .api }
316
def get_available_user_FIELD_transitions(instance, user, field):
317
"""
318
List of transitions available in current model state with all conditions
319
met and user has rights on it.
320
321
Parameters:
322
- instance: Model instance
323
- user: User instance for permission checking
324
- field: FSM field instance
325
326
Returns:
327
Generator yielding Transition objects available to the user
328
"""
329
```
330
331
Direct usage example:
332
333
```python
334
from django_fsm import get_available_FIELD_transitions
335
336
class Order(models.Model):
337
status = FSMField(default='pending')
338
339
def check_order_transitions(order):
340
# Use utility function directly
341
field = Order._meta.get_field('status')
342
available = list(get_available_FIELD_transitions(order, field))
343
344
for transition in available:
345
print(f"Available transition: {transition.name}")
346
```