or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

dynamic-states.mdexceptions.mdfield-types.mdindex.mdmodel-mixins.mdsignals.mdtransitions.mdvisualization.md

field-types.mddocs/

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

```