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.

пре 5 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <!doctype html>
  2. <html lang=fr>
  3. <head>
  4. <!-- Always define the charset before the title -->
  5. <meta charset=utf-8>
  6. <title>Modélisation d&#39;un workflow linéaire avec Django — Biologeek — David Larlet</title>
  7. <!-- Define a viewport to mobile devices to use - telling the browser to assume that the page is as wide as the device (width=device-width) and setting the initial page zoom level to be 1 (initial-scale=1.0) -->
  8. <meta name="viewport" content="width=device-width, initial-scale=1"/>
  9. <!-- Fake favicon, to avoid extra request to the server -->
  10. <link rel="icon" href="data:;base64,iVBORw0KGgo=">
  11. <link type="application/atom+xml" rel="alternate" title="Feed" href="/david/log/" />
  12. <link rel="manifest" href="/manifest.json">
  13. <link rel="stylesheet" href="/static/david/css/larlet-david-_J6Rv.css" data-instant-track />
  14. <noscript>
  15. <style type="text/css">
  16. /* Otherwise fonts are loaded by JS for faster initial rendering. See scripts at the bottom. */
  17. body {
  18. font-family: 'EquityTextB', serif;
  19. }
  20. h1, h2, h3, h4, h5, h6, time, nav a, nav a:link, nav a:visited {
  21. font-family: 'EquityCapsB', sans-serif;
  22. font-variant: normal;
  23. }
  24. </style>
  25. </noscript>
  26. <!-- Canonical URL for SEO purposes -->
  27. <link rel="canonical" href="https://larlet.fr/david/biologeek/archives/20070323-modelisation-d-un-workflow-lineaire-avec-django">
  28. </head>
  29. <body>
  30. <div>
  31. <header>
  32. <nav>
  33. <p>
  34. <small>
  35. Je suis <a href="/david/" title="Profil public">David Larlet</a>, <a href="/david/pro/" title="Activité professionnelle">artisan</a> du web qui vous <a href="/david/pro/accompagnement/" title="Activité d’accompagnement">accompagne</a><span class="more-infos"> dans l’acquisition de savoirs pour concevoir des <a href="/david/pro/produits-essentiels/" title="Qu’est-ce qu’un produit essentiel ?">produits essentiels</a></span>. <span class="more-more-infos">Discutons ensemble d’une <a href="/david/pro/devis/" title="En savoir plus">non-demande de devis</a>.</span> Je partage ici mes <a href="/david/blog/" title="Expériences bienveillantes">réflexions</a> et <a href="/david/correspondances/2017/" title="Lettres hebdomadaires">correspondances</a>.
  36. </small>
  37. </p>
  38. </nav>
  39. </header>
  40. <section>
  41. <h1 property="schema:name">Modélisation d&#39;un workflow linéaire avec Django</h1>
  42. <article typeof="schema:BlogPosting">
  43. <div property="schema:articleBody">
  44. <img src="/static/david/biologeek/images/logos/django.png" alt="vignette" style="float:left; margin: 0.5em 1em;" property="schema:thumbnailUrl" />
  45. <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>
  46. <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>
  47. <pre>class Step(models.Model):
  48. title = models.CharField()
  49. class Process(models.Model):
  50. title = models.CharField()
  51. class ProcessWorkflow(models.Model):
  52. source = models.ForeignKey(Step)
  53. target = models.ForeignKey(Step)
  54. process = models.ForeignKey(Process)</pre>
  55. <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>
  56. <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>
  57. <pre>def build_linear_workflow(items, steps=None, source=None):
  58. """ Recursive function to build a linear workflow, return a step list. """
  59. if steps is None:
  60. steps = []
  61. for item in items:
  62. if item.source == source:
  63. if item.target is None:
  64. return steps
  65. else:
  66. steps.append(item.target)
  67. return build_linear_workflow(items, steps, item.target)</pre>
  68. <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>
  69. <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>
  70. <pre>class Process(models.Model):
  71. title = models.CharField()
  72. def get_workflow(self):
  73. return build_linear_workflow(ProcessWorkflow.objects.filter(process=self.id))
  74. workflow = property(get_workflow)</pre>
  75. <p>On peut maintenant utiliser directement le workflow dans un template de la façon suivante&nbsp;:</p>
  76. <pre>&lt;h3&gt;{{ process.title }}&lt;/h3&gt;
  77. {% if process.workflow %}
  78. &lt;ul&gt;
  79. {% for step in process.workflow %}
  80. &lt;li&gt;{{ step.title }}&lt;/li&gt;
  81. {% endfor %}
  82. &lt;/ul&gt;
  83. {% endif %}</pre>
  84. <p>Simple comme Django :-).</p>
  85. <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>
  86. </div>
  87. </article>
  88. <footer>
  89. <h6 property="schema:datePublished">— 23/03/2007</h6>
  90. </footer>
  91. </section>
  92. <section>
  93. <div>
  94. <h3>Articles peut-être en rapport</h3>
  95. <ul>
  96. <li><a href="/david/biologeek/archives/20080902-sortie-de-django-10-une-annee-de-nouveautes/" title="Accès à Sortie de Django 1.0, une année de nouveautés">Sortie de Django 1.0, une année de nouveautés</a></li>
  97. <li><a href="/david/biologeek/archives/20071007-des-vacances-et-des-liens/" title="Accès à Des vacances et des liens">Des vacances et des liens</a></li>
  98. <li><a href="/david/biologeek/archives/20070807-une-solution-pour-faciliter-la-conception-d-applications-web-restful-avec-django/" title="Accès à Une solution pour faciliter la conception d&#39;applications web RESTful avec Django">Une solution pour faciliter la conception d&#39;applications web RESTful avec Django</a></li>
  99. </ul>
  100. </div>
  101. </section>
  102. <section>
  103. <div id="comments">
  104. <h3>Commentaires</h3>
  105. <div class="comment" typeof="schema:UserComments">
  106. <p class="comment-meta">
  107. <span class="comment-author" property="schema:creator">Olivier</span> le <span class="comment-date" property="schema:commentTime">24/03/2007</span> :
  108. </p>
  109. <div class="comment-content" property="schema:commentText">
  110. <p>Salut,<br />
  111. <br />
  112. Très intéressant ton article, mais qu'entends-tu par processus? et comment utilises-tu ces processus dans ton context?</p>
  113. </div>
  114. </div>
  115. <div class="comment" typeof="schema:UserComments">
  116. <p class="comment-meta">
  117. <span class="comment-author" property="schema:creator">Batiste</span> le <span class="comment-date" property="schema:commentTime">24/03/2007</span> :
  118. </p>
  119. <div class="comment-content" property="schema:commentText">
  120. <p>Merci pour cet exemple clair. Si j'ai bien compris, à partir d'un process, on peut modéliser une arborescence d'étapes à réaliser que l'on peut récupérer sous la forme d'une liste simple.<br />
  121. <br />
  122. D'où cette question : Peut gérer des structures arborescentes comme des listes imbriquées avec Django ? C'est une chose que je n'ai encore jamais vue. Le langage de template ne semble pas offrir cette fonctionnalité par défaut.</p>
  123. </div>
  124. </div>
  125. <div class="comment" typeof="schema:UserComments">
  126. <p class="comment-meta">
  127. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">24/03/2007</span> :
  128. </p>
  129. <div class="comment-content" property="schema:commentText">
  130. <p>@Olivier : des échantillons doivent suivre des suites d'étapes définies par les utilisateurs (expériences). Grâce à cette implémentation des workflows, je peux facilement représenter à l'écran ces suites d'étapes.<br />
  131. <br />
  132. @Batiste : bien sûr, dans l'exemple donné, si step possède un workflow lui aussi (concept de sous-étape), il suffit de faire une boucle sur step.workflow, et ainsi de suite avec une profondeur (quasi) infinie.</p>
  133. </div>
  134. </div>
  135. <div class="comment" typeof="schema:UserComments">
  136. <p class="comment-meta">
  137. <span class="comment-author" property="schema:creator">Damien B</span> le <span class="comment-date" property="schema:commentTime">27/03/2007</span> :
  138. </p>
  139. <div class="comment-content" property="schema:commentText">
  140. <p>Vous n'avez pas de bibliothèque pour XPDL en Python ?</p>
  141. </div>
  142. </div>
  143. <div class="comment" typeof="schema:UserComments">
  144. <p class="comment-meta">
  145. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">28/03/2007</span> :
  146. </p>
  147. <div class="comment-content" property="schema:commentText">
  148. <p>Tiens je ne connaissais pas, très intéressant !<br />
  149. <br />
  150. Pour l'instant la seule implémentation que j'ai trouvé en python est celle de CPS développée par Nuxeo : <a href="http://www.cps-project.org/sections/documentation/developers/cpsworkflow/switchLanguage/fr" title="http://www.cps-project.org/sections/documentation/developers/cpsworkflow/switchLanguage/fr" rel="nofollow">www.cps-project.org/secti...</a><br />
  151. <br />
  152. Je vais creuser de ce côté là, merci.</p>
  153. </div>
  154. </div>
  155. <div class="comment" typeof="schema:UserComments">
  156. <p class="comment-meta">
  157. <span class="comment-author" property="schema:creator">Miloz</span> le <span class="comment-date" property="schema:commentTime">17/07/2007</span> :
  158. </p>
  159. <div class="comment-content" property="schema:commentText">
  160. <p>J'ai l'impression que les projets de workflow en python un peu sérieux sont pas légions, surtout depuis que Zope est passé en v3; Les produits sous Zope v2 ne sont pas migrés, et Nuxeo abandonne python pour Java.<br />
  161. <br />
  162. Il y avait pourtant un projet, openflow, qui m'a l'air intéressant:<br />
  163. <a href="http://www.openflow.it/" title="http://www.openflow.it/" rel="nofollow">www.openflow.it/</a><br />
  164. <br />
  165. Ce serait à mon avis intéressant de le &quot;retranscrire&quot; sous Django; si ça intéresse qqun, j'ai commencé à modéliser quelques models ...</p>
  166. </div>
  167. </div>
  168. <div class="comment" typeof="schema:UserComments">
  169. <p class="comment-meta">
  170. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">17/07/2007</span> :
  171. </p>
  172. <div class="comment-content" property="schema:commentText">
  173. <p>Oh, très intéressant, je veux bien voir ce que ça peut donner !<br />
  174. <br />
  175. Pour l'instant j'ai commencé une implémentation from scratch car nos besoins sont très spécifiques mais je me suis grandement inspiré des workflows à activités comme openflow ou le module wfmc de Zope <a href="http://svn.zope.org/zope.wfmc/trunk/src/zope/wfmc/README.txt?rev=75443&amp;view=markup" title="http://svn.zope.org/zope.wfmc/trunk/src/zope/wfmc/README.txt?rev=75443&amp;view=markup" rel="nofollow">svn.zope.org/zope.wfmc/tr...</a><br />
  176. <br />
  177. Quoi qu'il en soit, mon adresse est sur la page de contact ;-).</p>
  178. </div>
  179. </div>
  180. <div class="comment" typeof="schema:UserComments">
  181. <p class="comment-meta">
  182. <span class="comment-author" property="schema:creator">Miloz</span> le <span class="comment-date" property="schema:commentTime">18/07/2007</span> :
  183. </p>
  184. <div class="comment-content" property="schema:commentText">
  185. <p>J'ai mis ça sous trac: <a href="https://opensvn.csie.org/traccgi/openflow" title="https://opensvn.csie.org/traccgi/openflow" rel="nofollow">opensvn.csie.org/traccgi/...</a><br />
  186. <br />
  187. J'ai repris le nom openflow, je dois pas avoir le droit mais bon ...<br />
  188. <br />
  189. Le projet openflow contient 3 applis:<br />
  190. <br />
  191. - workflow: implémentation style openflow<br />
  192. - leave: vide, destiné à recevoir une le clone de leave/openflow<br />
  193. - test: appli de test basique avec utilisation du framework test django 0.96</p>
  194. </div>
  195. </div>
  196. <div class="comment" typeof="schema:UserComments">
  197. <p class="comment-meta">
  198. <span class="comment-author" property="schema:creator">foufou</span> le <span class="comment-date" property="schema:commentTime">09/09/2008</span> :
  199. </p>
  200. <div class="comment-content" property="schema:commentText">
  201. <p>avec quel langega on peux réaliser ça, et quels sont ls outils necessaire pour créer un exemple d&#39;un workflow.</p>
  202. </div>
  203. </div>
  204. </div>
  205. </section>
  206. <footer>
  207. <nav>
  208. <p>
  209. <small>
  210. Je réponds quasiment toujours aux <a href="m&#x61;ilto:d&#x61;vid%40l&#x61;rlet&#46;fr" title="Envoyer un email">emails</a> (<a href="/david/signature/" title="Ma signature actuelle avec possibilité de chiffrement">signés</a>) et vous pouvez me rencontrer à Montréal. <span class="more-infos">N’hésitez pas à <a href="/david/log/" title="Être tenu informé des mises à jour">vous abonner</a> pour être tenu informé des publications récentes.</span>
  211. </small>
  212. </p>
  213. </nav>
  214. </footer>
  215. </div>
  216. <script src="/static/david/js/larlet-david-3ee43f.js" data-no-instant></script>
  217. <script data-no-instant>InstantClick.init()</script>
  218. </body>
  219. </html>