Expose REST Interface

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.

Endpoints

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.

Editable Fields

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.

Custom Serializer Per Transition

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().