Django models choices - allow only specific transitions on the admin interface

Viewed 25

for a models.IntegerField I can define easily choices with

sth = models.IntegerField(choices=(
    (1, 'sth1'),
    (2, 'sth2'),
    (3, 'sth3'),
))

. Is there any way where I can restrict the transitions from one value to another one?

For instance if the current value is '1', it can go only to '2', but if the current value is '3', it can go to '1' and '2', etc.

I need this restriction only on the admin interface. Is there anything built in for that?

Thanks.

2 Answers

You can make a subclass of the ModelForm to encode this logic:

STH_TRANSITIONS = {
    1: [2],
    2: [3],
    3: [1, 2]
}

class FSMModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        sth = self.fields['sth']
        trans = STH_TRANSITIONS.get(self.instance.sth)
        if trans is not None:
            sth.choices = [
                (k, v) for k, v in sth.choices
                if k == self.instance.sth or k in trans
            ]

Then you plug this in into the ModelAdmin of that model:

class MyModelAdmin(ModelAdmin):
    form = FSMModelForm

Seems that you want to implement a Finite State Machine. Something you can try is to use django-fsm together with django-fsm-admin. Those two packages allow you to specify from which state a transition is allowed into another state.

Related