Представьте себе приложение типа JIRA со сложным рабочим процессом. Для создания такого приложения требуется поддержка управления конечным автоматом. Если вы создаете свое приложение с помощью Django, Django FSM предоставляет вам готовую поддержку для управления конечным автоматом.
Предположим, что наше приложение имеет следующий рабочий процесс выполнение Task.
Основная модель для Task будет следующая:
from django.db import models class Task(models.Model): title = models.CharField(max_length=100, null=False) description = models.TextField()
Теперь давайте посмотрим, как мы можем выстроить этот рабочий процесс с помощью Django FSM.
$ pip install django-fsm
Или вы можете установить последнюю версию с git
$ pip install -e git://github.com/kmmbvnr/django-fsm.git#egg=django-fsm
Определим поле в модели как FSMState. Через это поле Django FSM будет выполнят переходы.
from django.db import models from django_fsm import FSMField class Task(models.Model): title = models.CharField(max_length=100, null=False) description = models.TextField() state = FSMField()
Мы определили поле FSMState, но пока еще мы не связывали с ним никаких состояний с этим полем. Мы можем сделать это следующим образом:
from django.db import models from django_fsm import FSMField STATES = ('Open', 'In Progress', 'Resolved', 'Re Opened', 'Closed') STATES = list(zip(STATES, STATES)) class Task(models.Model): title = models.CharField(max_length=100, null=False) description = models.TextField() state = FSMField(default=STATES[0], choices=STATES)
Django FSM предоставляет декоратор transition. После того, как вы декорируете метод модели с помощью этого декоратора, вы можете вызвать метод модели для выполнения перехода на каждом объекте модели.
from django.db import models from django_fsm import FSMField, transition STATES = ('Open', 'In Progress', 'Resolved', 'Re Opened', 'Closed') STATES = list(zip(STATES, STATES)) class Task(models.Model): ... state = FSMField(default=STATES[0], choices=STATES) @transition(field=state, source=['Open', 'Re Opened'], target='In Progress') def start(self): """ Этот метод будет содержать действие, которое необходимо предпринять после того как измениться state. Например, уведомление пользователей. """ pass @transition(field=state, source='In Progress', target='Resolved') def resolve(self): pass
Параметр source принимает список состояний или отдельное состояние из которого возможен переход. Вы можете использовать * для source, чтобы разрешить переключение на цель (target) из любого состояния. Параметр field принимает как имя строкового атрибута, так и фактический экземпляр поля.
Чтобы изменить состояние объекта, вызовите метод модели, который декорирован декоратором transition.
task = Task.objects.get(pk=task_id) task.start()
Если start() успешно выполнено без каких-либо исключений, состояние объекта задачи будет обновлено, но не будет сохранено в базе данных. Вызовите метод save(), чтобы сохранить объект в базе данных.
task.save()
Могут быть ситуации, когда вы захотите проверить определенное условие перед выполнением перехода. Для этого в Django FSM, используется параметр conditions декоратора transition. Conditions должен быть списком функций, принимающих один аргумент (экземпляр модели). Функция/метод должны возвращать значение True или False.
Метод conditions может быть обычной функцией Python.
def can_close(instance): """ Return True or False, depending upon some condition """ pass
или это может быть методом модели.
def can_close(self): """ Return True or False, depending upon some conditions """ pass
conditions используется таким образом:
@transition(field=state, source='Resolved', target='Closed', conditions=[can_close]) def close(self): """ This method will contain the action that needs to be taken once the state is changed. """ pass
Django FSM предоставляет способ установить резервное состояние в случае, если метод перехода вызывает исключение.
@transition(field=state, source='Resolved', target='Closed', on_error='failed') def close(self): """ Some exception could happen here """ pass
Декоратор transition имеет параметр permission, который можно использовать для проверки разрешения перед выполнением перехода. Permission принимает строку разрешения или вызываемую функцию, которая ожидает аргументы экземпляра и пользователя и возвращает True, если пользователь может выполнить переход.
@transition(field=state, source='Resolved', target='Closed', permission='myapp.can_change_task') def close(self): """ This method will contain the action that needs to be taken once state is changed. """ pass
или
@transition(field=state, source='Resolved', target='Closed', permission=lambda instance, user: not user.has_perm('myapp.can_change_task')) def close(self): """ This method will contain the action that needs to be taken once the state is changed. """ pass
Вы можете проверить разрешение с помощью метода has_transition_permission.
from django_fsm import has_transition_perm def publish_view(request, task_id): task = get_object_or_404(Task, pk=task_id) if not has_transition_perm(task.close, request.user): raise PermissionDenied task.close()
Вы можете сгенерировать диаграмму перехода состояний на основе методов перехода.
Вам понадобится pip install graphviz> = 0.4 а так же не забудьте добавьте django_fsm в вашу INSTALLED_APPS
INSTALLED_APPS = ( ... 'django_fsm', ... )
Теперь выполните следующую команду.
$ ./manage.py graph_transitions -o task_transitions.png myapp.Task
Django FSM имеет все, что вам нужно для управления конечным автоматом в вашем приложении. В дополнение к этому, если вы хотите выполнять переходы с панель администратора, используйте Django-FSM-admin. Также вы можете вести журналы переходов, используя Django-FSM-log.
Оригинальная статья: A Guide to Managing Finite State Machine Using Django FSM
Краткий перевод: https://vuejs.org/guide/components/v-model.html Основное использование v-model используется для реализации двусторонней привязки в компоненте. Начиная с Vue…
Сегодня мы рады объявить о выпуске Vue 3.4 «🏀 Slam Dunk»! Этот выпуск включает в…
Vue.js — это универсальный и адаптируемый фреймворк. Благодаря своей отличительной архитектуре и системе реактивности Vue…
Недавно, у меня истек сертификат и пришлось заказывать новый и затем устанавливать на хостинг с…
Каким бы ни было ваше мнение о JavaScript, но всем известно, что работа с датами…
Все, кто следит за последними событиями в мире адаптивного дизайна, согласятся, что введение контейнерных запросов…