Field definitions
Field types
FSMField
Use FSMField to store state as a string value.
from django_fsm import FSMField, FSMModelMixin
class BlogPost(FSMModelMixin, models.Model):
state = FSMField(default='new')
FSMIntegerField
Use FSMIntegerField for enum-style states.
class BlogPostStateEnum(object):
NEW = 10
PUBLISHED = 20
HIDDEN = 30
class BlogPostWithIntegerField(FSMModelMixin, models.Model):
state = FSMIntegerField(default=BlogPostStateEnum.NEW)
FSMKeyField
Use FSMKeyField to store state values in a table and maintain FK
integrity.
class DbState(FSMModelMixin, models.Model):
id = models.CharField(primary_key=True)
label = models.CharField()
def __str__(self):
return self.label
class BlogPost(FSMModelMixin, models.Model):
state = FSMKeyField(DbState, default='new')
In your fixtures/initial_data.json:
[
{
"pk": "new",
"model": "myapp.dbstate",
"fields": {
"label": "_NEW_"
}
},
{
"pk": "published",
"model": "myapp.dbstate",
"fields": {
"label": "_PUBLISHED_"
}
}
]
Note: source and target use the PK values of the DbState model as
names, even if the field is accessed without the _id postfix.
Field options
protected
Use protected=True to prevent direct assignment. Only transitions may
change the state.
Because refresh_from_db assigns to the field, protected fields raise there
as well unless you use FSMModelMixin. Use FSMModelMixin by default to
allow refresh without enabling arbitrary writes elsewhere.
from django_fsm import FSMModelMixin
class BlogPost(FSMModelMixin, models.Model):
state = FSMField(default='new', protected=True)
model = BlogPost()
model.state = 'invalid' # Raises AttributeError
model.refresh_from_db() # Works