Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save harshithjv/7f586150dc4ae5bf13a10d42cb021a78 to your computer and use it in GitHub Desktop.

Select an option

Save harshithjv/7f586150dc4ae5bf13a10d42cb021a78 to your computer and use it in GitHub Desktop.
Integrating django model and transitions library without django-transitions library

By default, state variable is attached to any model object that is passed to Machine object initalisation in transitions library. Passing model_attribute will allow us to define custom state attribute. This wasn't obvious while going through the document. TL;DR 📖🥱😜

https://github.com/pytransitions/transitions

Also django-transitions is like experimental repo and maintained since Jan 2019. So I was looking for the solution without using it. Even if we use it mentioned only about setting custom name in Mixins. Does not make sense to just to use mixins for custom variables. So example I shown in models.py is better way. Next, I need to see how I can inherit this feature into custom ModelField class.

Sample execution:

$ ./manage.py shell
Python 3.8.0 (default, Feb 25 2021, 22:10:10) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.23.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from testapp.models import Car

In [2]: car = Car(title="Ford", color="red")

In [3]: car
Out[3]: <Car: Red - Ford [On Factory]>

In [4]: car.state_field
Out[4]: 'on_factory'

In [5]: car.machine.states.keys()
Out[5]: odict_keys(['on_factory', 'in_showroom', 'sold'])

In [6]: car.sell()
---------------------------------------------------------------------------
MachineError                              Traceback (most recent call last)
... (suppressed tracback to shorten text length)
MachineError: "Can't trigger event sell from state on_factory!"

In [7]: car.buy()
Out[7]: True

In [8]: car.state_field
Out[8]: 'in_showroom'

In [9]: car.sell()
Out[9]: True

In [10]: car
Out[10]: <Car: Red - Ford [Sold]>

In [11]: Car.objects.all()
Out[11]: <QuerySet [<Car: Blue - Maruthi [In Showroom]>, <Car: Red - Ford [Sold]>]>

I got inspired to write this gist after looking at issue #111 and replied with the same code in the comment section.

from django.db import models
from django.utils.translation import gettext as _
from transitions import Machine
class Car(models.Model):
title = models.CharField(_('title'), max_length=100)
color = models.CharField(_('color'), max_length=50)
state_field = models.CharField(_('state field'), max_length=50, default='on_factory', editable=False)
CAR_STATES = ['on_factory', 'in_showroom', 'sold']
CAR_TRANSITIONS = [
{'trigger': 'buy', 'source': 'on_factory', 'dest': 'in_showroom', 'after': 'update_state_field'},
{'trigger': 'sell', 'source': 'in_showroom', 'dest': 'sold', 'after': 'update_state_field'},
]
def __init__(self, *args, **kwargs):
models.Model.__init__(self, *args, **kwargs)
self.machine = Machine(self, states=AnotherCar.CAR_STATES,
transitions=AnotherCar.CAR_TRANSITIONS,
initial=self.state_field,
model_attribute="state_field") // To specify the custom state name
def update_state_field(self):
self.save()
def __str__(self):
return f"{self.color.title()} - {self.title} [{self.state_field.replace('_', ' ').title()}]"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment