Repository with sources and generator of https://larlet.fr/david/ https://larlet.fr/david/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

article.md 3.7KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. title: Modélisation d'un workflow linéaire avec Django
  2. slug: modelisation-d-un-workflow-lineaire-avec-django
  3. date: 2007-03-23 22:55:48
  4. type: post
  5. vignette: images/logos/django.png
  6. contextual_title1: Sortie de Django 1.0, une année de nouveautés
  7. contextual_url1: 20080902-sortie-de-django-10-une-annee-de-nouveautes
  8. contextual_title2: Des vacances et des liens
  9. contextual_url2: 20071007-des-vacances-et-des-liens
  10. contextual_title3: Une solution pour faciliter la conception d'applications web RESTful avec Django
  11. contextual_url3: 20070807-une-solution-pour-faciliter-la-conception-d-applications-web-restful-avec-django
  12. <p>Pour le boulot, je devais réaliser un prototype implémentant des processus simples, c'est-à-dire représentés par une suite d'étapes ordonnées. On peut facilement se représenter un tel processus en considérant une ligne de métro avec ses stations sans ramifications.</p>
  13. <p>C'est relativement simple à énoncer mais c'est un peu plus difficile à modéliser, commençons par le modèle de données appliqué à Django (simplifié)&nbsp;:</p>
  14. <pre>class Step(models.Model):
  15. title = models.CharField()
  16. class Process(models.Model):
  17. title = models.CharField()
  18. class ProcessWorkflow(models.Model):
  19. source = models.ForeignKey(Step)
  20. target = models.ForeignKey(Step)
  21. process = models.ForeignKey(Process)</pre>
  22. <p>On dispose donc maintenant d'étapes et de processus. La classe/table ProcessWorkflow permet de lier les étapes entre elles au sein d'un processus.</p>
  23. <p>Une fois ce modèle créé, il s'agit de reconstruire le workflow lorsqu'on en a besoin. Pour cela, un fonction récursive permet assez élégamment de se sortir d'affaire. C'est peut-être ici qu'il peut y avoir mieux en termes de performance mais dans le cadre de mon prototype c'est suffisant&nbsp;:</p>
  24. <pre>def build_linear_workflow(items, steps=None, source=None):
  25. """ Recursive function to build a linear workflow, return a step list. """
  26. if steps is None:
  27. steps = []
  28. for item in items:
  29. if item.source == source:
  30. if item.target is None:
  31. return steps
  32. else:
  33. steps.append(item.target)
  34. return build_linear_workflow(items, steps, item.target)</pre>
  35. <p>La fonction est relativement générique car elle me permet de former des workflows d'étapes, de processus, de projets, etc. Je pense qu'elle est relativement facile à comprendre avec le nom des variables choisies (le problème de performance est au niveau de la boucle sur l'ensemble des items, je pense que je pourrais facilement retirer l'item ajouté à steps).</p>
  36. <p>Il ne reste plus qu'à ajouter cette ressource sous la forme d'un propriété au précédent modèle, la classe Process devient alors&nbsp;:</p>
  37. <pre>class Process(models.Model):
  38. title = models.CharField()
  39. def get_workflow(self):
  40. return build_linear_workflow(ProcessWorkflow.objects.filter(process=self.id))
  41. workflow = property(get_workflow)</pre>
  42. <p>On peut maintenant utiliser directement le workflow dans un template de la façon suivante&nbsp;:</p>
  43. <pre>&lt;h3&gt;{{ process.title }}&lt;/h3&gt;
  44. {% if process.workflow %}
  45. &lt;ul&gt;
  46. {% for step in process.workflow %}
  47. &lt;li&gt;{{ step.title }}&lt;/li&gt;
  48. {% endfor %}
  49. &lt;/ul&gt;
  50. {% endif %}</pre>
  51. <p>Simple comme Django :-).</p>
  52. <p>Voici le fruit de mes recherches, merci à tous ceux qui ont contribué au résultat final, n'hésitez pas à réagir si vous avez une solution plus simple/élégante. La prochaine étape, c'est de passer aux workflows plus complexes, pouvant présenter des arborescences ascendantes et/ou descendantes. Le casse-tête ne fait que commencer...</p>