Marcos de trabajo para Django

He estado buscando un marco para simplificar el desarrollo de flujos de trabajo razonablemente complejos en las aplicaciones de Django. Me gustaría poder utilizar el marco para automatizar las transiciones de estado, permisos y tal vez algunos extras como el registro de auditoría y las notificaciones.

He visto información más antigua sobre el mismo tema, pero no demasiado en los últimos 2 o 3 años. Las principales opciones de las que he oído hablar son GoFlow (no se actualiza desde 2/2009) y django-workflow (parece más activo).

¿Alguien ha usado estos paquetes? ¿Son maduros y / o compatibles con Django moderno (1.3)? ¿Hay otras opciones que valga la pena considerar que podrían ser mejor o mejor compatibles?

Permítanme dar algunas notas aquí ya que soy el autor de django-fsm y django-viewflow, dos proyectos que podrían llamarse “bibliotecas de flujo de trabajo”.

La palabra de flujo de trabajo en sí está un poco sobrevalorada. Diferentes tipos de bibliotecas y software podrían llamarse a sí mismos “flujo de trabajo”, pero tienen una funcionalidad variable. La característica común es que un flujo de trabajo conecta los pasos de algún proceso en un todo.

Clasificación general

Como veo, los enfoques de implementación del flujo de trabajo se pueden clasificar de la siguiente manera:

  • Usuarios únicos / múltiples : si la biblioteca de flujo de trabajo automatiza las tareas de un solo usuario o tiene opciones de verificación de permiso / asignación de tareas.
  • Secuencial / Paralelo – El flujo de trabajo secuencial es solo una implementación de patrón de máquina de estado y permite tener un solo estado activo en un momento. Los flujos de trabajo paralelos permiten tener varias tareas activas a la vez, y probablemente tengan algún tipo de funcionalidad de sincronización / unión paralela.
  • Explícito / implícito : si el flujo de trabajo se representa como una entidad externa separada, o se teje en alguna otra clase, esa responsabilidad principal es diferente.
  • Estático / dynamic : los flujos de trabajo estáticos se implementan en el código de Python una vez y luego se ejecutan; los flujos de trabajo dynamics normalmente se pueden configurar cambiando los contenidos de las tablas de la base de datos del flujo de trabajo. Los flujos de trabajo estáticos suelen estar mejor integrados con el rest de la infraestructura de django, como vistas, formularios y plantillas, y admiten una mejor personalización mediante las construcciones python habituales, como la herencia de clases. Los flujos de trabajo dynamics suponen que tiene una interfaz genérica que se puede adaptar a cualquier cambio en el tiempo de ejecución del flujo de trabajo.

De estos, los primeros dos podrían considerarse diferencias graduales, pero los otros dos son fundamentales.

Paquetes específicos

Aquí hay una breve descripción de lo que tenemos hoy en django, djangopackages y la lista de proyectos awesome-django en la sección de flujo de trabajo:

  • django.contrib.WizardView : implícito, usuario único, secuencial, estático, la implementación de flujo de trabajo más simple que podríamos tener. Almacena el estado intermedio en los datos de publicación del formulario oculto.
  • django-flows – flujo de trabajo explícito, de usuario único, secuencial, estático , que mantiene el estado de flujo en el almacenamiento externo, para permitir al usuario cerrar o abrir la página en otra pestaña y continuar trabajando.
  • django-fsm : flujo de trabajo implícito, multiusuario, secuencial y estático : la biblioteca de máquinas de estado más compacta y liviana. Eventos de cambio de estado representados como llamadas de métodos de python de la clase de modelo. Tiene soporte rudimentario para herencia de flujo y anulaciones. Proporciona espacios para permisos de asociado con transiciones de estado. Permite usar un locking optimista para evitar actualizaciones de estado concurrentes.
  • django-states : flujo de trabajo explícito, multiusuario, secuencial y estático con clases separadas para las transiciones de estados y máquinas. Transiciones hechas pasando el nombre de la cadena de transición al método make_transition. Proporciona la forma de permiso asociado con transiciones de estado. Tiene un punto final genérico REST simple para cambiar los estados del modelo usando llamadas AJAX. El soporte de herencia de máquina de estado no se menciona en la documentación, pero la definición de estado de clase lo hace posible con ninguna o pocas modificaciones de la biblioteca principal.
  • django_xworkflows : flujo de trabajo estático, explícito y secuencial sin soporte para la comprobación de permisos del usuario, clase separada para la máquina de estados. Utiliza tuplas para las definiciones de estado y de transición, lo que hace que el soporte de herencia de flujo de trabajo sea difícil.
  • django-workflows : flujo de trabajo explícito, multiusuario, secuencial y dynamic que almacena el estado en los modelos django proporcionados por la biblioteca. Tiene una forma de adjuntar permisos para la transición del flujo de trabajo, y básicamente eso es todo.

Ninguna de estas bibliotecas de máquinas de estado django admite flujos de trabajo paralelos, lo que limita mucho su ámbito de aplicación. Pero hay dos que hacen:

  • django-viewflow : flujo de trabajo explícito, multiusuario, paralelo, estático , con soporte para la ejecución de tareas paralelas, división compleja y semántica de unión. Proporciona ayudantes para integrarse con las vistas basadas en clase y funcionales de django, y diferentes consultas de ejecución de tareas en segundo plano, y diversas estrategias de locking pesimistas y optimistas para evitar actualizaciones concurrentes.

  • GoFlow , mencionado en la pregunta, tiende a ser el flujo de trabajo explícito, multiusuario, paralelo y dynamic , pero ha sido abandonado por el autor durante años.

Veo la forma de implementar la funcionalidad dinámica de construcción de flujo de trabajo sobre django-viewflow . Tan pronto como se complete, cerrará el último y más sofisticado caso para la implementación del flujo de trabajo en el mundo django.

Hope, si alguien hubiera podido leer hasta ahora, ahora entiende mejor el término de flujo de trabajo y puede hacer la elección consciente para la biblioteca de flujo de trabajo para su proyecto.

¿Hay otras opciones que valga la pena considerar que podrían ser mejor o mejor compatibles?

Sí.

Pitón.

No necesita un producto de flujo de trabajo para automatizar las transiciones de estado, la autorización y, tal vez, algunos extras como el registro de auditoría y las notificaciones.

Hay una razón por la cual no hay muchos proyectos que hacen esto.

  • El patrón de diseño del Estado es bastante fácil de implementar.

  • Las reglas de Autorización (“permiso”) ya son una parte de primera clase de Django.

  • El registro ya es una parte de primera clase de Python (y se ha agregado a Django). Usar esto para el registro de auditoría es una tabla de auditoría u otro registrador (o ambos).

  • El marco de mensaje (“notificaciones”) ya es parte de Django.

¿Qué más necesitas? Ya lo tienes todo.

El uso de definiciones de clase para el patrón de diseño de estado y decoradores para autorización y registro funciona tan bien que no necesita nada más allá de lo que ya tiene.

Lea esta pregunta relacionada: Implementación de un “motor de reglas” en Python

Un paquete escrito por un asociado mío, django-fsm , parece funcionar: es bastante liviano y suficientemente funcional para ser útil.

Es gracioso porque habría estado de acuerdo con S.Lott sobre el uso de Python como lo es para un motor de reglas. Tengo una perspectiva COMPLETAMENTE diferente ahora que lo he hecho.

Si desea un motor de reglas completas, necesita bastantes piezas móviles. Creamos un motor de reglas completo de Python / Django y se sorprendería de lo que necesita ser incorporado para poner en marcha un gran motor de reglas. Explicaré más detalles, pero primero el sitio web es http://nebrios.com .

Un motor de reglas debería tener al menos:

  • Listas de control de acceso : ¿quieres que todos vean todo?
  • API de par clave / valor : KVP almacena el estado y todas las reglas reactjsn a los estados modificados.
  • Modo de depuración : poder ver cada estado cambiado, qué lo cambió y por qué. Supremo.
  • Interacción a través de formularios web y correo electrónico : poder crear rápidamente un formulario web es una gran ventaja, junto con el análisis sistemático de los correos electrónicos entrantes.
  • ID de proceso : estos rastrean un “hilo” de valor comercial. De lo contrario, los procesos se superpondrían continuamente.
  • Mucho más!

Así que prueba Nebri, o los otros que menciono a continuación para ver si satisfacen tus necesidades.

Aquí está el modo de depuración

enter image description here

Una forma generada automáticamente

enter image description here

Una regla de flujo de trabajo de ejemplo:

class task_sender(NebriOS): # send a task to the person it got assigned to listens_to = ['created_date'] def check(self): return (self.created_date is not None) and (self.creator_status != "complete") and (self.assigned is not None) def action(self): send_email (self.assigned,""" The ""{{task_title}}"" task was just sent your way! Once you finish, send this email back to log the following in the system: i_am_finished := true It will get assigned back to the task creator to look over. Thank you!! - The Nebbs """, subject="""{{task_title}}""") 

Por lo tanto, no, no es sencillo crear un motor de flujo de trabajo basado en eventos y basado en reglas solo en Python. ¡Hemos estado en esto más de un año! Yo recomendaría usar herramientas como

Puedo agregar una biblioteca más que admite cambios sobre la marcha en los componentes del flujo de trabajo a diferencia de sus equivalentes.

Mira el río django

ActivFlow : un motor de flujo de trabajo genérico, liviano y extensible para el desarrollo ágil y la automatización de operaciones complejas de procesos comerciales.

¡Puede tener todo un flujo de trabajo modelado en poco tiempo!

Paso 1: Registro de la aplicación Workflow

 WORKFLOW_APPS = ['leave_request'] 

Paso 2: Configuración de la actividad

 from activflow.core.models import AbstractActivity, AbstractInitialActivity from activflow.leave_request.validators import validate_initial_cap class RequestInitiation(AbstractInitialActivity): """Leave request details""" employee_name = CharField( "Employee", max_length=200, validators=[validate_initial_cap]) from = DateField("From Date") to = DateField("To Date") reason = TextField("Purpose of Leave", blank=True) def clean(self): """Custom validation logic should go here""" pass class ManagementApproval(AbstractActivity): """Management approval""" approval_status = CharField(verbose_name="Status", max_length=3, choices=( ('APP', 'Approved'), ('REJ', 'Rejected'))) remarks = TextField("Remarks") def clean(self): """Custom validation logic should go here""" pass 

Paso 3: Definición de flujo

 FLOW = { 'initiate_request': { 'name': 'Leave Request Initiation', 'model': RequestInitiation, 'role': 'Submitter', 'transitions': { 'management_approval': validate_request, } }, 'management_approval': { 'name': 'Management Approval', 'model': ManagementApproval, 'role': 'Approver', 'transitions': None } } 

Paso 4: Reglas de negocios

 def validate_request(self): return self.reason == 'Emergency' 

Migro el django-goflow de django 1.X -python 2.X para adaptarlo a django 2.X-python 3.x, el proyecto está en django2-goflow