django_fsm.rest.FlowRESTMixin adds transition endpoints to Django REST
Framework viewsets. Install the REST dependencies with
pip install 'django-fsm[rest]'.
This integration works without Viewflow. The example uses Separate Flow Classes,
including the flow’s on_success callback that saves the new state.
from rest_framework import serializers, viewsets
from django_fsm.rest import FlowRESTMixin
from .flow import ReportFlow
from .models import Report
class ReportSerializer(serializers.ModelSerializer):
class Meta:
model = Report
fields = ('pk', 'text', 'state_field')
read_only_fields = ('state_field',)
class ReportViewSet(FlowRESTMixin, viewsets.ModelViewSet):
flow_state = ReportFlow.state_field
queryset = Report.objects.all()
serializer_class = ReportSerializer
Register the viewset with a DRF router as usual. The mixin constructs
ReportFlow(obj); override get_object_flow(self, request, obj) when your
flow needs additional context.
Relative to the viewset’s URL prefix:
GET /{pk}/transition/ returns the current state and outgoing transitions,
with their labels, condition results, permissions, and action URLs.POST /{pk}/transition/{slug}/ checks permissions and conditions, saves
allowed request fields, and runs the transition in one database transaction.GET /chart/ returns a JSON object containing the chart’s dot source.Transition requests cannot edit model fields by default. Whitelist fields for each transition:
def get_transition_fields(self, request, obj, slug):
return ['text'] if slug == 'approve' else []
Only these request keys reach the serializer; other keys are ignored. The serializer’s normal validation and read-only restrictions still apply.
During a transition request, self.action contains the transition slug:
def get_serializer_class(self):
if self.action == 'approve':
return ApprovalSerializer
return super().get_serializer_class()
Define ApprovalSerializer for your application and keep its writable
fields consistent with get_transition_fields().