Registry / web-framework / django-fsm

django-fsm

JSON →
library3.0.1pypypi✓ verified 23d ago

Django FSM (Finite State Machine) provides declarative state management for Django models. It allows defining states and transitions using decorators, ensuring state changes adhere to predefined rules. The standalone `django-fsm` library, currently at version 3.0.1, is deprecated; its functionality has been integrated into `viewflow.fsm` since version 3.0.0. The original library will no longer receive updates.

pip install django-fsm
INSTALL
IMPORT
SIG · DJANGO-FSM
D
django-fsm
web-frameworkpythonv3.0.1
Install
3.2s avg
Import
Disk
231MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v3.0.1 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.910 runs
installs and imports cleanly · install 0.0s · import 0.000s · 198.5MB
glibc
py 3.103.910 runs
installs and imports cleanly · install 3.2s · import 0.000s · 270MB
231MB installed
● package 231MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

FSMField
from django_fsm import FSMField
from django_fsm import FSMField

This quickstart demonstrates defining states with `FSMField` and transitions with the `@transition` decorator for a `BlogPost` model. It highlights basic state transitions and the use of `protected=True` to enforce transitions via methods only. Note that for versions 3.0.0 and above, the functionality has migrated to `viewflow.fsm`.

import os import django from enum import Enum from django.db import models from django_fsm import FSMField, transition os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'your_project_name.settings') # Replace with actual project settings if needed django.setup() class BlogPost(models.Model): class BlogState(models.TextChoices): DRAFT = "draft", "Draft" REVIEW = "review", "Under Review" PUBLISHED = "published", "Published" ARCHIVED = "archived", "Archived" state = FSMField(choices=BlogState.choices, default=BlogState.DRAFT, protected=True) title = models.CharField(max_length=255) content = models.TextField() @transition(field=state, source=BlogState.DRAFT, target=BlogState.REVIEW) def submit_for_review(self): print(f"Blog post '{self.title}' submitted for review.") @transition(field=state, source=BlogState.REVIEW, target=BlogState.PUBLISHED) def publish(self): print(f"Blog post '{self.title}' published!") @transition(field=state, source=[BlogState.DRAFT, BlogState.REVIEW, BlogState.PUBLISHED], target=BlogState.ARCHIVED) def archive(self): print(f"Blog post '{self.title}' archived.") def __str__(self): return f"{self.title} ({self.get_state_display()})" # Example Usage (assuming a Django environment is set up and models are synced) # For a real application, replace this with actual model creation/retrieval. # try: # blog_post = BlogPost.objects.create(title="My First Post", content="Lorem ipsum...") # print(blog_post) # if can_proceed(blog_post.submit_for_review): # blog_post.submit_for_review() # blog_post.save() # print(blog_post) # if can_proceed(blog_post.publish): # blog_post.publish() # blog_post.save() # print(blog_post) # if can_proceed(blog_post.archive): # blog_post.archive() # blog_post.save() # print(blog_post) # # This would fail if protected=True and not using a transition method # # blog_post.state = BlogPost.BlogState.DRAFT # # blog_post.save() # except Exception as e: # print(f"An error occurred: {e}")
Debug
Known issues
breakingThe standalone `django-fsm` library (version 3.0.0+) is no longer maintained. Its functionality has been fully integrated into `viewflow` as the `viewflow.fsm` package. Users are strongly encouraged to migrate to `viewflow.fsm` for new features and ongoing maintenance.
fix
Migrate existing code to use `viewflow.fsm` classes and decorators. Refer to the `viewflow` documentation for the new API, particularly the migration guide if available. The core concepts of FSM remain, but import paths and class structures have changed significantly.
affects: >=3.0.0
gotchaCalling a transition method (e.g., `model_instance.transition_method()`) changes the state only in memory. You *must* call `model_instance.save()` afterward to persist the state change to the database.
fix
Always follow a successful transition method call with `model_instance.save()`.
affects: All
gotchaIf `FSMField(protected=True)` is used, direct assignment to the state field (e.g., `model.state = 'new_state'`) will raise an `AttributeError`. State changes must occur via decorated transition methods. This is often desired for strict state machine enforcement.
fix
Ensure all state modifications go through methods decorated with `@transition`. If direct assignment is temporarily needed (e.g., for migrations or testing), set `protected=False` or bypass FSM checks carefully.
affects: All
breakingThe default `db_index=True` for `FSMIntegerField` was removed in version 2.2.0. This could subtly affect database performance if you relied on it for indexing.
fix
If `db_index` is required for `FSMIntegerField` instances, explicitly set `db_index=True` when defining the field in your model (e.g., `state = FSMIntegerField(db_index=True)`).
affects: >=2.2.0
Upgrade
Version history
3.0.1latest on PyPI · released Oct 7, 2025
Audit
Dependencies
DjangorequiredCore framework dependency for integration.
viewflowoptionalThe successor library for `django-fsm` functionality (from v3.0.0 onwards).
django-fsm-logoptionalCommonly used for logging FSM transitions in Django Admin.
pygraphvizoptionalRequired for graph_transition command to visualize state machines.
Agent activity
22 hits · last 30 days
node
20
Amazon
1
Resources