{"id":1392,"date":"2011-04-30T18:24:00","date_gmt":"2011-04-30T16:24:00","guid":{"rendered":"http:\/\/j-mad.com\/blog\/?p=1392"},"modified":"2011-04-30T18:24:00","modified_gmt":"2011-04-30T16:24:00","slug":"django-extended-choices-lapp-qui-te-donne-le-choix-mais-pas-la-date","status":"publish","type":"post","link":"https:\/\/j-mad.com\/blog\/2011\/04\/30\/django-extended-choices-lapp-qui-te-donne-le-choix-mais-pas-la-date\/","title":{"rendered":"Django-extended-choices, l&#8217;app qui te donne le choix (mais pas la date)"},"content":{"rendered":"<p>J&#8217;avais plein d&#8217;app possible \u00e0 pr\u00e9senter pour ce billet du mois d&#8217;avril. Mais en r\u00e9fl\u00e9chissant, je me suis dit que la meilleure app possible \u00e0 pr\u00e9senter ce moi-si c&#8217;\u00e9tait celle qui a \u00e9t\u00e9 lib\u00e9r\u00e9 pendant les DjangoCongs \u00e0 savoir Django-extended-choices.<\/p>\n<p>Et en plus, ce qui est bien, c&#8217;est que comme c&#8217;est une toute petite app, \u00e7a ne sera pas fatiguant du tout d&#8217;\u00e9crire ce billet.<\/p>\n<h2>1- O\u00f9 on le trouve, comment on l\u2019installe, tout \u00e7a quoi (et la doc)&nbsp;?<\/h2>\n<p>L\u00e0 c&#8217;est tout simple, on la trouve sur github. Et uniquement sur github. Quand \u00e0 la doc elle tient toute enti\u00e8re dans le fichier Readme.rst qui se trouve lui aussi sur github. (et vous la trouverez aussi en docstring de l&#8217;unique classe que contient l&#8217;app).<\/p>\n<p>Pour l&#8217;installation il suffit ou plut\u00f4t il faut forc\u00e9ment, cloner le repo github.<\/p>\n<h2>2- Mais au fait, \u00e0 quoi \u00e7a sert&nbsp;?<\/h2>\n<p>A g\u00e9rer d&#8217;une mani\u00e8re propre les Choices que l&#8217;on peut avoir \u00e0 mettre en place dans les fields Django.&nbsp; Parce qu&#8217;il est vrai que la m\u00e9thode normale, \u00e0 base de constantes que l&#8217;on ne sait pas trop o\u00f9 d\u00e9clarer et de tuples de tuples, me si elle fonctionne bien, n&#8217;est pas super \u00e9l\u00e9gante.<\/p>\n<p>L&#8217;app permet donc d&#8217;encapsuler tout \u00e7a dans une belle petite classe<\/p>\n<h2>3- Comment \u00e7a marche&nbsp;?<\/h2>\n<p>Bon la je vais, sans aucun remords, faire un petit copi\u00e9\/coll\u00e9 de la doc. Parce que l&#8217;explication de comment \u00e7a marche est tr\u00e8s bien faite.<\/p>\n<p>Donc en fait cela marche comme \u00e7a&nbsp;:<\/p>\n<div class=\"codecolorer-container python default\" style=\"overflow:auto;white-space:nowrap;width:435px;\"><div class=\"python codecolorer\"><span class=\"kw1\">from<\/span> extended_choices <span class=\"kw1\">import<\/span> Choices<br \/>\n<br \/>\nSTATES <span class=\"sy0\">=<\/span> Choices<span class=\"br0\">&#40;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#40;<\/span><span class=\"st0\">'ONLINE'<\/span><span class=\"sy0\">,<\/span> &nbsp;<span class=\"nu0\">1<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'Online'<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#40;<\/span><span class=\"st0\">'DRAFT'<\/span><span class=\"sy0\">,<\/span> &nbsp; <span class=\"nu0\">2<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'Draft'<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#40;<\/span><span class=\"st0\">'OFFLINE'<\/span><span class=\"sy0\">,<\/span> <span class=\"nu0\">3<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'Offline'<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span><br \/>\n<span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">class<\/span> ContentModel<span class=\"br0\">&#40;<\/span>models.<span class=\"me1\">Model<\/span><span class=\"br0\">&#41;<\/span>:<br \/>\n&nbsp; &nbsp; title &nbsp; &nbsp; &nbsp;<span class=\"sy0\">=<\/span> models.<span class=\"me1\">CharField<\/span><span class=\"br0\">&#40;<\/span>max_length<span class=\"sy0\">=<\/span><span class=\"nu0\">255<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; content &nbsp; &nbsp;<span class=\"sy0\">=<\/span> models.<span class=\"me1\">TextField<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; state &nbsp; &nbsp; &nbsp;<span class=\"sy0\">=<\/span> models.<span class=\"me1\">PositiveSmallIntegerField<\/span><span class=\"br0\">&#40;<\/span>choices<span class=\"sy0\">=<\/span>STATES.<span class=\"me1\">CHOICES<\/span><span class=\"sy0\">,<\/span> default<span class=\"sy0\">=<\/span>STATES.<span class=\"me1\">DRAFT<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; related_to <span class=\"sy0\">=<\/span> models.<span class=\"me1\">ManyToManyField<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'self'<\/span><span class=\"sy0\">,<\/span> through<span class=\"sy0\">=<\/span><span class=\"st0\">&quot;ContentToContent&quot;<\/span><span class=\"sy0\">,<\/span> symmetrical<span class=\"sy0\">=<\/span><span class=\"kw2\">False<\/span><span class=\"sy0\">,<\/span> blank<span class=\"sy0\">=<\/span><span class=\"kw2\">True<\/span><span class=\"sy0\">,<\/span> null<span class=\"sy0\">=<\/span><span class=\"kw2\">True<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">def<\/span> <span class=\"kw4\">__unicode__<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw2\">self<\/span><span class=\"br0\">&#41;<\/span>:<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> u<span class=\"st0\">'Content &quot;%s&quot; (state=%s)'<\/span> % <span class=\"br0\">&#40;<\/span><span class=\"kw2\">self<\/span>.<span class=\"me1\">title<\/span><span class=\"sy0\">,<\/span> STATES.<span class=\"me1\">CHOICES_DICT<\/span><span class=\"br0\">&#91;<\/span><span class=\"kw2\">self<\/span>.<span class=\"me1\">state<\/span><span class=\"br0\">&#93;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">def<\/span> get_related_content<span class=\"br0\">&#40;<\/span><span class=\"kw2\">self<\/span><span class=\"br0\">&#41;<\/span>:<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"kw2\">self<\/span>.<span class=\"me1\">related_to<\/span>.<span class=\"me1\">select_related<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>.<span class=\"kw2\">filter<\/span><span class=\"br0\">&#40;<\/span>state<span class=\"sy0\">=<\/span>STATES.<span class=\"me1\">ONLINE<\/span><span class=\"br0\">&#41;<\/span><\/div><\/div>\n<p>plut\u00f4t clair non&nbsp;?<\/p>\n<p>Et cela remplace ce code l\u00e0&nbsp;:<\/p>\n<div class=\"codecolorer-container python default\" style=\"overflow:auto;white-space:nowrap;width:435px;height:300px;\"><div class=\"python codecolorer\">STATE_ONLINE\u00a0 <span class=\"sy0\">=<\/span> <span class=\"nu0\">1<\/span><br \/>\nSTATE_DRAFT\u00a0\u00a0 <span class=\"sy0\">=<\/span> <span class=\"nu0\">2<\/span><br \/>\nSTATE_OFFLINE <span class=\"sy0\">=<\/span> <span class=\"nu0\">3<\/span><br \/>\n<br \/>\nSTATE_CHOICES <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#40;<\/span>STATE_ONLINE<span class=\"sy0\">,<\/span> &nbsp;<span class=\"st0\">'Online'<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#40;<\/span>STATE_DRAFT<span class=\"sy0\">,<\/span> &nbsp; <span class=\"st0\">'Draft'<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#40;<\/span>STATE_OFFLINE<span class=\"sy0\">,<\/span> <span class=\"st0\">'Offline'<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">,<\/span><br \/>\n<span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\nSTATE_DICT <span class=\"sy0\">=<\/span> <span class=\"kw2\">dict<\/span><span class=\"br0\">&#40;<\/span>STATE_CHOICES<span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">class<\/span> ContentModel<span class=\"br0\">&#40;<\/span>models.<span class=\"me1\">Model<\/span><span class=\"br0\">&#41;<\/span>:<br \/>\n&nbsp; &nbsp; title &nbsp; &nbsp; &nbsp;<span class=\"sy0\">=<\/span> models.<span class=\"me1\">CharField<\/span><span class=\"br0\">&#40;<\/span>max_length<span class=\"sy0\">=<\/span><span class=\"nu0\">255<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; content &nbsp; &nbsp;<span class=\"sy0\">=<\/span> models.<span class=\"me1\">TextField<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; state &nbsp; &nbsp; &nbsp;<span class=\"sy0\">=<\/span> models.<span class=\"me1\">PositiveSmallIntegerField<\/span><span class=\"br0\">&#40;<\/span>choices<span class=\"sy0\">=<\/span>STATE_CHOICES<span class=\"sy0\">,<\/span> default<span class=\"sy0\">=<\/span>STATE_DRAFT<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; related_to <span class=\"sy0\">=<\/span> models.<span class=\"me1\">ManyToManyField<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'self'<\/span><span class=\"sy0\">,<\/span> through<span class=\"sy0\">=<\/span><span class=\"st0\">&quot;ContentToContent&quot;<\/span><span class=\"sy0\">,<\/span> symmetrical<span class=\"sy0\">=<\/span><span class=\"kw2\">False<\/span><span class=\"sy0\">,<\/span> blank<span class=\"sy0\">=<\/span><span class=\"kw2\">True<\/span><span class=\"sy0\">,<\/span> null<span class=\"sy0\">=<\/span><span class=\"kw2\">True<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">def<\/span> <span class=\"kw4\">__unicode__<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw2\">self<\/span><span class=\"br0\">&#41;<\/span>:<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> u<span class=\"st0\">'Content &quot;%s&quot; (state=%s)'<\/span> % <span class=\"br0\">&#40;<\/span><span class=\"kw2\">self<\/span>.<span class=\"me1\">title<\/span><span class=\"sy0\">,<\/span> STATE_DICT<span class=\"br0\">&#91;<\/span><span class=\"kw2\">self<\/span>.<span class=\"me1\">state<\/span><span class=\"br0\">&#93;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">def<\/span> get_related_content<span class=\"br0\">&#40;<\/span><span class=\"kw2\">self<\/span><span class=\"br0\">&#41;<\/span>:<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"kw2\">self<\/span>.<span class=\"me1\">related_to<\/span>.<span class=\"me1\">select_related<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>.<span class=\"kw2\">filter<\/span><span class=\"br0\">&#40;<\/span>state<span class=\"sy0\">=<\/span>STATE_ONLINE<span class=\"br0\">&#41;<\/span><\/div><\/div>\n<p>Personnellement, je trouve que la notation point\u00e9e&nbsp; STATES.CHOICES ou&nbsp; STATES.DRAFT est bien bien plus clair que la notation pr\u00e9c\u00e9dente.<\/p>\n<h4>Conclusion<\/h4>\n<p>Une petite app qui ne fait qu&#8217;une chose mais qui le fait bien. A utiliser de partout donc. (Il ne manque juste que des tests ..:) ) .<\/p>\n","protected":false},"excerpt":{"rendered":"<p>J&#8217;avais plein d&#8217;app possible \u00e0 pr\u00e9senter pour ce billet du mois d&#8217;avril. Mais en r\u00e9fl\u00e9chissant, je me suis dit que la meilleure app possible \u00e0 pr\u00e9senter ce moi-si c&#8217;\u00e9tait celle qui a \u00e9t\u00e9 lib\u00e9r\u00e9 pendant les DjangoCongs \u00e0 savoir Django-extended-choices. Et en plus, ce qui est bien, c&#8217;est que comme c&#8217;est une toute petite app, &hellip; <a href=\"https:\/\/j-mad.com\/blog\/2011\/04\/30\/django-extended-choices-lapp-qui-te-donne-le-choix-mais-pas-la-date\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Django-extended-choices, l&#8217;app qui te donne le choix (mais pas la date)<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[35],"tags":[99,98],"class_list":["post-1392","post","type-post","status-publish","format-standard","hentry","category-la-django-app-du-mois","tag-django","tag-python"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p12cdp-ms","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/posts\/1392","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/comments?post=1392"}],"version-history":[{"count":2,"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/posts\/1392\/revisions"}],"predecessor-version":[{"id":1394,"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/posts\/1392\/revisions\/1394"}],"wp:attachment":[{"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/media?parent=1392"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/categories?post=1392"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/tags?post=1392"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}