2011-01-07 28 views
3

Ich arbeite daran, eine Workflow-Engine in meinem Projekt zu implementieren und der Hauptzweck meines Versuchs ist es, eine portable App zu erstellen. Etwas, das ich in Zukunft in jedes andere Projekt einfügen könnte, und dann Workflows an verschiedene Modelle in meinen Projekten anhängen und sie zum Laufen bringen.Django Workflow-Engine mit Signalen und Sellerie-Django

Ich habe versucht, an einen Ansatz zu denken, aber es scheint nicht das perfekte Setup zu sein. Ich dachte daran, eine Workflow-App in meinem Projekt zu erstellen, zwei Arten von Modellen anzuhängen, einige enthalten die Einrichtung eines Workflow (Workflow, Schritte, Aktionen) und andere Modelle enthalten die Instanzen/Transaktionen.

Unten ist mein Workflow/models.py

from django.db import models 
from django.contrib.contenttypes.models import ContentType 
from django.contrib.contenttypes import generic 
import signals 


################################ 
# Workflow engine models 
################################ 

class Signal_Listener(models.Model): 
    LISTENING_ON = (
    ('I', 'INSERT'), 
    ('U', 'UPDATE'), 
    ('D', 'DELETE'), 
    ('S', 'SELECT'), 
    ('A', 'ANY QUERY'), 
    ('L', 'ANY DDL'), 
    ) 

    table_name = models.CharField(max_length=100) 
    listening_to = models.CharField(max_length=1, choices=LISTENING_ON) 

    class Meta: 
     unique_together = (("table_name", "listening_to"),) 

    def __unicode__(self): 
     return '%s - %s' % (self.table_name, self.listening_to) 

class Action(models.Model): 
    ACTION_TYPE_CHOICES = (
    ('P', 'Python Script' ), 
    ('C', 'Class name'  ), 
    ) 
    name = models.CharField(max_length=100) 
    action_type = models.CharField(max_length=1, choices=ACTION_TYPE_CHOICES) 
    audit_obj = generic.GenericRelation('core.Audit', editable=False) 

class Steps(models.Model): 
    sequence = models.IntegerField() 
    Action = models.ForeignKey(Action) 
    Signal_Listener = models.ForeignKey(Signal_Listener) 

class Process(models.Model): 
## TODO: Document 
# Processes class is used to store information about the process itself. 
# Or in another word, the workflow name. 
    WF_TYPE_LIST = (
    ('P', 'Python-API'), 
    ) 

    name = models.CharField(max_length=30) 
    is_active = models.BooleanField() 
    wf_type = models.CharField(max_length=1, choices=WF_TYPE_LIST) 
    audit_obj = generic.GenericRelation('core.Audit', editable=False) 
    listening_to = models.ForeignKey(Steps) 



################################ 
# Workflow transactions models 
################################ 

class Instance(models.Model): 
## TODO: Document 
# Re 
    INSTANCE_STATUS = (
    ('I', 'In Progress'), 
    ('C', 'Cancelled' ), 
    ('A', 'Archived' ), # Old completed tasks can be archived 
    ('P', 'Pending' ), 
    ('O', 'Completed' ) 
    ) 

    id = models.CharField(max_length=200, primary_key=True) 
    status = models.CharField(max_length=1, choices=INSTANCE_STATUS, db_index=True) 
    audit_obj = generic.GenericRelation('core.Audit', editable=False) 

    def save(self, *args, **kwargs): 
    # on new records generate a new uuid 
     if self.id is None or self.id.__len__() is 0: 
      import uuid 

      self.id = uuid.uuid4().__str__() 
     super(Instances, self).save(*args, **kwargs) 

class Task(models.Model): 
    TASK_STATUS = (
    ('S', 'Assigned' ), 
    ('I', 'In Progress'), 
    ('P', 'Pending' ), 
    ('C', 'Cancelled' ), 
    ('A', 'Archived' ), # Old completed tasks can be archived 
    ('O', 'Completed' ) 
    ) 
    name = models.CharField(max_length=100) 
    instance = models.ForeignKey(Instance) 
    status = models.CharField(max_length=1, choices=TASK_STATUS) 
    bio = models.CharField(max_length=100) 
    audit_obj = generic.GenericRelation('core.Audit', editable=False) 

und ich habe auch ein Workflow/signals.py

""" 
     Workflow Signals 
      Will be used to monitor all inserts, update, delete or select statements 
      If an action is attached to that particular table, it will be inserted Celery-Tasks distribution. 
    """ 
    from django.db.models.signals import post_save, post_delete 
    from django.core.cache import cache 


    def workflow_post_init_listener(sender, **kwargs): 
     try: 

      if cache.get('wf_listner_cache_%s' % kwargs['instance']._meta.db_table): 
       pass 
      else: 
       record = 'Signal_Listener'.objects.get(table_name__exact=kwargs['instance']._meta.db_table) 
# am not sure what to do next! 
     except 'Signal_Listener'.DoesNotExist: 
      # TODO: Error logging 
      pass 

    post_save.connect(workflow_post_init_listener, dispatch_uid="workflow.models.listener.save") 

Ich glaube, mein Design-Modell könnte auch verbessert werden müssen. Ich könnte in verschiedenen Szenarien verwenden und ich dachte, mit dem Genehmigungszyklus zu beginnen, zum Beispiel könnte ich den table_name/model_name in signal_listener einfügen, um auf neue Einsätze zu überwachen. Wenn ja, werde ich einen bestimmten Workflow auslösen.

Wie für Aktionen, ich verstehe, dass Aktionen entwickelt werden müssen. Vielleicht muss ich unter der Workflow-App einen Aktionsordner erstellen und jede Aktion in eine Klasse einfügen. Jeder wird eine bestimmte Aufgabe des Sendens von E-Mails, Archivierung, Update-Datenbank-Wert .. etc

Wenn das Rad neu erfinden und wenn es so etwas gibt, das bereits entwickelt wurde, kann jemand vorschlagen, ich wäre mehr als glücklich durchgehen.

Mit freundlichen Grüßen,

+0

Ich denke, Ihre Frage könnte umformuliert werden. Es ist nicht klar, was du wirklich fragst. – roman

Antwort

2

Zum Beispiel können Sie einen Blick für zope.wfmc haben kann (http://pypi.python.org/pypi/zope.wfmc): Dies ist eine Implementierung eines workflow Management Coalition Workflow, der auf XPDL definiert werden kann.

Verwandte Themen