Skip to main content

django-fsm

Django-friendly finite state machine support.

django-fsm adds simple, declarative state management for Django models and plain Python objects.

Instead of managing states with ad-hoc string fields and writing error-prone assignments across views and models, you define states and transitions explicitly. Transitions validate source and target states, enforce business conditions, check user permissions, and keep side-effects clean.

Installation

python -m pip install django-fsm

For plain Python classes, no other dependencies are required. To use with Django models, make sure Django is installed or specify the extra:

python -m pip install 'django-fsm[django]'

Quick start

Add an FSMField to your Django model and mark transition methods with the @transition decorator:

from django.db import models
from django_fsm import FSMField, transition, can_proceed

class BlogPost(models.Model):
    state = FSMField(default='draft', protected=True)

    @transition(field=state, source='draft', target='published')
    def publish(self):
        """Side-effects when publishing a post (e.g. notify users, update cache)."""

The protected=True option prevents direct state modification:

post = BlogPost()
post.state = 'published'  # Raises AttributeError

To invoke a transition and persist the change:

post = BlogPost.objects.get(pk=post_id)

if can_proceed(post.publish):
    post.publish()
    post.save()

Conditions and Permissions

Conditions

Use the conditions argument to enforce rules before a transition is allowed. Conditions are callables that take the model instance and return a boolean:

def can_publish(instance):
    return bool(instance.title and instance.body)

class BlogPost(models.Model):
    state = FSMField(default='draft')

    @transition(field=state, source='draft', target='published', conditions=[can_publish])
    def publish(self):
        pass

Permissions

You can guard transitions with permissions and verify them using has_transition_perm:

from django_fsm import transition, has_transition_perm

class BlogPost(models.Model):
    state = FSMField(default='draft')

    @transition(field=state, source='draft', target='published', permission='blog.can_publish')
    def publish(self):
        pass

In your view:

if not has_transition_perm(post.publish, request.user):
    raise PermissionDenied

post.publish()
post.save()

Dynamic Targets

When the target state depends on runtime logic or method results:

  • RETURN_VALUE(*allowed_states) selects the target from the method’s return value:

from django_fsm import FSMField, RETURN_VALUE, transition

class Task(models.Model):
    status = FSMField(default='pending')

    @transition(field=status, source='pending', target=RETURN_VALUE('approved', 'rejected'))
    def review(self, score):
        return 'approved' if score >= 80 else 'rejected'
  • GET_STATE(func, states=[...]) calculates the target state before the transition runs, based on the instance and method arguments.

Plain Python State Machines

State also works with plain Python classes without Django database models or settings:

from django_fsm import State

class Review:
    state = State(states=None, default='draft')

    @state.transition(source='draft', target='published')
    def publish(self):
        pass

review = Review()
review.publish()
assert review.state == 'published'

Viewflow Pro Integrations

django-fsm integrates out of the box with Viewflow Pro and Django REST Framework:

  • django_fsm.admin.FlowAdminMixin: Viewflow Admin integration for state workflows.

  • django_fsm.viewset.FlowViewsMixin: Viewflow Viewset workflows.

  • django_fsm.rest.FlowRESTMixin: Optional Django REST Framework viewset integration (requires django-fsm[rest]).

Documentation & Contributing

License

Django FSM is licensed under AGPL-3.0-or-later with the viewflow-library-exception. See LICENSE and LICENSE_EXCEPTION for details.

Metadata

Release files for django-fsm 5.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-fsm 5.0.0
File Size Uploaded Provenance Actions
django_fsm-5.0.0.tar.gz 72.5 kB Without provenance Details for django_fsm-5.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for django-fsm 5.0.0
File Interpreter ABI Platform Actions
django_fsm-5.0.0-py3-none-any.whl Python 3 none any Details for django_fsm-5.0.0-py3-none-any.whl

Total release size: 118.3 kB

Release files / django_fsm-5.0.0.tar.gz

Download URL django_fsm-5.0.0.tar.gz
Size 72.5 kB
Tags Source
SHA-256 checksum
How to use checksums
aa6833a6477b1512a98d7e599f3ae527e71028bcc5615a8e842422b05423d9e2
BLAKE2b-256 checksum
How to use checksums
0542a8407ac3dc5a908673594556eaee721d5f09627ffe9050554fc896ff1d96
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release files / django_fsm-5.0.0-py3-none-any.whl

Download URL django_fsm-5.0.0-py3-none-any.whl
Size 45.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6fd9bc9510d47708e1e5249dcbd893420ec69b4f1b8cb0391fa90d8195436b55
BLAKE2b-256 checksum
How to use checksums
15ae959287c49eb8fd6cd2ca1b5d1d239e910b5150c28ac7e1243833e142fb0f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Security for django-fsm 5.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page