Package: drf-fsm
===============
Django FSM with Django Rest Framework.Overviewdrf_fsm library provides an endpoint for defined each transition in models using Django FSM with Django Rest Framework library.FeaturesThis library provides endpoint for each transition of FSM and customize like:Easy to define the number of FSM fields that's the endpoint you want to create automatically. default : No field.Easy to define how many transitions endpoint you want to create for particular field: default: all transition of fields.Easy to define serializer for each transition and field name wise: default: serializer_class of ViewSet.Easy to handle response for each endpoint of transition and field, default: serializer.data .InstallationInstall drf_fsm using pip::pip install drf_fsmImport Mixin from drf_fsm and Use in ViewSet views of DRF::from drf_fsm.mixins import FsmViewSetMixinUses with exampleLets Suppose a Post model that uses Django FSMmodels.py::from django.contrib.auth import get_user_model
from django.db import models
from django_fsm import transition, FSMField

User = get_user_model()


class PostStatusChoices(models.TextChoices):
    Draft = 'draft', 'Draft'
    Pending = 'pending', 'Pending'
    Publish = 'publish', 'Publish'
    Future = 'future', 'Future'
    Trash = 'trash', 'Trash'


class Post(models.Model):
    title = models.CharField(max_length=200, unique=True)
    slug = models.SlugField(max_length=200, unique=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
    updated_on = models.DateTimeField(auto_now=True)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    status = FSMField('Status', max_length=20, default=PostStatusChoices.Draft,
                      choices=PostStatusChoices.choices, protected=True)

    @transition(field=status, source='*', target=PostStatusChoices.Draft)
    def draft(self):
        pass

    @transition(field=status, source=PostStatusChoices.Draft, target=PostStatusChoices.Pending)
    def pending(self):
        pass

    @transition(field=status, source=PostStatusChoices.Pending, target=PostStatusChoices.Publish)
    def publish(self):
        pass

    @transition(field=status, source=PostStatusChoices.Pending, target=PostStatusChoices.Future)
    def future(self):
        pass

    @transition(field=status, source='*', target=PostStatusChoices.Trash)
    def trash(self):
        passWe define model with 5 choices above and added 5 transition for each status in model.Now create ViewSet for Post modelviews.py::from rest_framework.viewsets import ModelViewSet
from drf_fsm.mixins import FsmViewSetMixin
from .models import Post
from .serializers import PostSerializer


class PostViewSet(FsmViewSetMixin, ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    fsm_fields = ['status']Here we define "status" as a FSM field, we can define multiple in list if we have multiple in single modelConnect this views to DRF router
urls.py::from rest_framework.routers import DefaultRouter
from .views import PostViewSet

router = DefaultRouter()

router.register('post', PostViewSet, basename="post_view_set")

urlpatterns = router.urlsFinished. Cheers ✌️Now checking Output in Swagger.. image:: output.png
:width: 100%😎 :),Let's move to customizations:CustomizationsDefine number of fields of FSM in view like::fsm_fields = ['status', 'priority']Define particular transitions for include, left will ignore for endpoints.
suppose field name is "status" and have 5 transition according above example so we can
handle which transition should include and other ignore.So write @classmethod in viewset for override this feature::@classmethod
def status_transitions(cls):  # Here status in field name so it's dynamic based on FSM field name.
return ['trash', 'publish']Here "trash" and "publish" transition endpoint will available for API, other will ignore from endpointsDefine serializer class for each transition or field name wise::publish_status_serializer_class = PublishStatusPostSerializer # {transition}_{field_name}_serializer_classorstatus_serializer_class = StatusPostSerializer  # {field_name}_serializer_classor, defaultserializer_class = PostSerializer  # Default serializer class for eachSerializer class uses dynamic name for each transition if define otherwise default will use.Define Response of each transition::def publish_status_response(self, serializer): # {transition}_{field_name}_response
     return {"message": "Post status updated published"}

 or

 def status_response(self, serializer): # {field_name}_response, but it'll show for all transition of status field
     return {"message": "Post status updated"}

 or, default

 serializer.dataFinished Customizations.. image::https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png:target:https://www.buymeacoffee.com/sainiprayLicensedrf_fsm is an Open Source project licensed under the terms of theMIT license <https://github.com/sainipray/drf-fsm/blob/main/LICENSE>_