<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>blog ntic de revolunet &#187; Python</title>
	<atom:link href="http://blog.revolunet.com/index.php/conseil.intranet/developpement/python/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.revolunet.com</link>
	<description>Blog des Nouvelles Technologies de l'Information et de la Communication</description>
	<lastBuildDate>Thu, 05 Jan 2012 11:03:32 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Django internationalisation made easy with i18n</title>
		<link>http://blog.revolunet.com/index.php/general/django-internationalisation-with-i18n</link>
		<comments>http://blog.revolunet.com/index.php/general/django-internationalisation-with-i18n#comments</comments>
		<pubDate>Wed, 08 Sep 2010 20:12:03 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[django]]></category>

		<guid isPermaLink="false">http://blog.revolunet.com/?p=431</guid>
		<description><![CDATA[Ok so now you have your new django based killer app you&#8217;d like to translate it into several languages. Here&#8217;s a quick memo to get all this running quickly.
Django provides all the tools you need to do this effectively. You can use simple string translations or create more advanced rules with various plurals forms, variable [...]]]></description>
			<content:encoded><![CDATA[<p>Ok so now you have your new django based killer app you&#8217;d like to translate it into several languages. Here&#8217;s a quick memo to get all this running quickly.</p>
<p>Django provides all the tools you need to do this effectively. You can use simple string translations or create more advanced rules with various <a href="http://docs.djangoproject.com/en/dev/topics/i18n/internationalization/#pluralization" target="_blank">plurals forms, variable interpolations</a>&#8230;</p>
<p>First, be sure to use UTF-8 encode anywhere in your project :</p>
<ul>
<li>Save your file as UTF-8 (check your text editor)</li>
<li>Declare python files encoding with this at the top of each python file (see <a href="http://www.python.org/dev/peps/pep-0263/" target="_blank">PEP 263</a>) :<br />
# -*- encoding: UTF-8 -*-</li>
<li><a href="http://www.python.org/dev/peps/pep-0263/" target="_blank">Define your strings as unicode</a> if needed</li>
<li>Be warned : mixing encodings and charsets in a project can cause hasardous/mystical issues then massive headaches</li>
</ul>
<p>Django provides several builtin tools to help you internationalise :</p>
<ul>
<li><strong>makemessages</strong> command : scan your code to extract definition and create a .po file</li>
<li><strong>compilemessages </strong>command : compile your translations in the .po files to .mo</li>
<li><strong>django.middleware.locale.LocaleMiddleWare </strong>: Autodetect user language (from browser) or use session defined language (or fallback to project default)</li>
<li><strong>django.core.context_processors.i18n</strong>: add LANGUAGE_CODE and LANGUAGES variables to your templates</li>
<li><strong>django.conf.urls.i18n </strong>: a view that accepts a language POST parameter to change session language</li>
<li><strong>django.views.i18n.javascript_catalog </strong>: provides a javascript array with the translations and helpers functions gettext&#8230;</li>
</ul>
<p><b>So lets internationalise our project :</b><br />
<br />
Django make it easier to work with app level localisations and not project-global files.<br />
So you must create a ‘locale’ subfolder for each app you want to localize.<br />
Create a ‘fr’ and ‘en’ folder inside each ‘locale’ folder. (or more if needed)<br />
Try first to translate a first app in a second language before going on.<br />
</p>
<h2>Activate django.middleware.locale.LocaleMiddleWare and tweak your settings.py :</h2>
<pre class="brush: python">
# -*- encoding: UTF-8 -*-

TIME_ZONE = &#039;Europe/Paris&#039;
LANGUAGE_CODE = &#039;fr-FR&#039;
USE_I18N = True

# see http://code.djangoproject.com/browser/django/trunk/django/conf/global_settings.py
gettext = lambda s: s
LANGUAGES = (
(&#039;fr&#039;, gettext(u&#039;French&#039;)),
(&#039;en&#039;, gettext(&#039;English&#039;)),
)

MIDDLEWARE_CLASSES = (
&#039;django.contrib.sessions.middleware.SessionMiddleware&#039;,
&#039;django.middleware.locale.LocaleMiddleware&#039;,
&#039;django.middleware.common.CommonMiddleware&#039;,
&#039;django.contrib.auth.middleware.AuthenticationMiddleware&#039;,
)

TEMPLATE_CONTEXT_PROCESSORS = (
&quot;django.core.context_processors.auth&quot;,
&quot;django.core.context_processors.debug&quot;,
&quot;django.core.context_processors.i18n&quot;,
&quot;django.core.context_processors.media&quot;,
&quot;django.core.context_processors.debug&quot;,
)
</pre>
<h2>Add a lang toolbar to your template and connect to the django.conf.urls.i18n view :</h2>
<p>Add a simple lang bar to your base template :</p>
<pre class="brush: html">
   {% load i18n %}
    &lt;div id=&#039;langbar&#039; style=&#039;text-align:right;padding-top:5px;&#039;&gt;
        &lt;form name=&#039;langform&#039; style=&#039;margin:0px;display:inline;width:200px&#039; action=&#039;/i18n/setlang/&#039; method=&#039;POST&#039;&gt;
            {% for LANG in LANGUAGES  %}
                &lt;img src=&#039;{{ MEDIA_URL }}img/flags/{{ LANG.0 }}.png&#039; title=&quot;{% trans LANG.1 %}&quot; style=&#039;margin:5px;cursor:pointer&#039; onclick=&quot;document.langform.language.value=&#039;{{ LANG.0 }}&#039;;document.langform.submit();&quot;&gt;
            {% endfor %}
            &lt;input name=&#039;language&#039; type=hidden value=&quot;{{ LANGUAGE_CODE }}&quot;&gt;
            current LANG : {{ LANGUAGE_CODE }}
        &lt;/form&gt;
    &lt;/div&gt;
</pre>
<p>As you can see, when you enable i18n context processor, your templates can acces <a target="_blank" href="http://docs.djangoproject.com/en/dev/ref/templates/api/#django-core-context-processors-i18n">new variables</a> like LANGUAGE_CODE or LANGUAGES</p>
<p>Now add the /i18n/setlang/ view in your urls.py.<br />
This view accepts language POST parameter then redirect user to REFERER page (or one designed with ?next GET parameter). Selected language is then kept in session.</p>
<pre class="brush: python">
urlpatterns += patterns(&#039;&#039;,
    (r&#039;^i18n/&#039;, include(&#039;django.conf.urls.i18n&#039;)),
)
</pre>
<p>Now, check if when you submit the form, the selected language is kept in session. If not check your database (need the session table), restart your dev server or enable settings.DEBUG  <img src='http://blog.revolunet.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>If you can submit your lang and LANGUAGE_CODE is kept in session, <strong>bravo</strong>, your django is multilingual ready. </p>
<h2>Internationalise your code</h2>
<p>In your templates : just load i18n then replace every string with a <a target="_blank" href="http://docs.djangoproject.com/en/dev/topics/i18n/internationalization/#trans-template-tag">trans tag</a></p>
<pre class="brush: html">
{% load i18n %}
&lt;div class=&quot;main&quot;&gt;{% trans &quot;Welcome to our new website&quot; %}&gt;&lt;/div&gt;
{% block contents %}&lt;img src=&quot;/img/intro-{{ LANGUAGE_CODE }}&quot;/&gt;{% trans &quot;This is the intro&quot; %}{% block %}
</pre>
<p>In your views : just import django.utils.translation.gettext then replace every string with gettext(thestring)</p>
<pre class="brush: python">
from django.utils.translation import gettext as _ # just a shortcut
def view(request):
    hello = _(&#039;Hello, World&#039;)
    return HttpResponse(&#039;&lt;b&gt;%s&lt;/b&gt;&#039; % hello)
</pre>
<p>Now each time you run the makemessages command for this app, it will detect these string and update this app django.po files accordingly.</p>
<h2>Generate the .po, traduct then compile to .mo</h2>
<ol>
<li><strong>From this app folder</strong>, run
<pre class="brush: bash">python ../manage.py makemessages --all</pre>
<p>This will scan this app .py and .html files for gettext/trans calls and generate or update a django.po file for each lang.</li>
<li>Now you can edit (manually) this old-fashionned-style .po file with your favorite  text editor.<br />
If your site default is English, edit app/locale/fr/LC_MESSAGES/django.po (and djangojs.po if needed)</li>
<li>Once all your strings are translated, run
<pre class="brush: bash">python ../manage.py compilemessages</pre>
<p>from the <strong>app root</strong>. This will generate .mo files from the .po</li>
</ol>
<p>Now your templates and views should be automagically translated.</p>
<p>run makemessages/compilemessages commands to update the .po and .mo when you change some code. restart the web server.</p>
<h2>Javascript internationalisation</h2>
<p>Now your templates and views are correctly translated, you may also need  to internationalise jour javascript files.</p>
<p>Django provide a simple solution that you can use in your projects</p>
<ul>
<li>the <b>makemessages</b> command takes a -d djangojs parameter to parse .js files and create a djangojs.po</li>
<li>The <b>django.views.i18n.javascript_catalog</b> provides a way to acces the .po files from javascript</li>
<li>This view serves a javascript file containing a &#8216;catalog&#8217; array with translations and utilities functions such as <strong>gettext</strong></li>
</ul>
<p><b>Activate the view in your urls.py</b> :<br />
<br />I tweaked the <a target="_blank" href="http://docs.djangoproject.com/en/dev/topics/i18n/internationalization/#module-django.views.i18n">official rule</a> a bit.</p>
<pre class="brush: python">
# urls.py
def jsi18n(request, packages = None, domain = None):
    if not domain:
        domain = &#039;djangojs&#039;
    from django.views.i18n import javascript_catalog
    return javascript_catalog(request, domain, packages)

urlpatterns += patterns(&#039;&#039;,
    (r&#039;^jsi18n/?(?P&lt;packages&gt;[^/]+)?/?(?P&lt;domain&gt;[^/]+)?/?$&#039;, jsi18n ),                                          # serves the javascript data
)
</pre>
<p>Add a javascript include in your template ( be sure to include it before any other javascript localised file) :</p>
<pre class="brush: html">
	&lt;script type=&quot;text/javascript&quot; src=&quot;/jsi18n/main/djangojs&quot;&gt;&lt;/script&gt;
</pre>
<p>This url will serves you a javascript file from project/main/locale/fr/LC_MESSAGES/djangojs.po (if user lang is fr)<br />
<br />
By default, this language definition returns the user LANGUAGE_CODE but you can override using ?language GET parameter</p>
<p>Now you just need to replace each string in your javascript files with a call to gettext.</p>
<pre class="brush: javascript">
alert( gettext(&quot;Ready to start ?&quot;) );
</pre>
<h2>Maintain</h2>
<p>When you add new code, always use calls to gettext instead of strings.<br />
run makemessages to update the .po definitions<br />
translate new strings in the .po files<br />
run compilemessages to update</p>
<p></p>
<p><b>Voila</b> Now your app can speak any UTF-8 lang, which is more than 600 languages <img src='http://blog.revolunet.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>These are just the basics, check out for the full story <a target="_blank" href="http://docs.djangoproject.com/en/dev/topics/i18n/internationalization/">http://docs.djangoproject.com/en/dev/topics/i18n/internationalization/</a></p>
<p><strong>Notes/Gotchas</strong> :</p>
<ul>
<li>Using builtin dev server, you need to restart after a compilemessages</li>
<li>Use <a href="http://www.famfamfam.com/lab/icons/flags/" target="_blank">famfamfam flag icons</a></li>
<li>You must add your app to settings.INSTALLED_APPS if you want to use jsi18n view for this app</li>
<li>Double check middlewares order, and session tables</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.revolunet.com/index.php/general/django-internationalisation-with-i18n/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Astuces Django</title>
		<link>http://blog.revolunet.com/index.php/developpement/astuces-django</link>
		<comments>http://blog.revolunet.com/index.php/developpement/astuces-django#comments</comments>
		<pubDate>Fri, 11 Dec 2009 00:46:07 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[developpement]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.revolunet.com/?p=393</guid>
		<description><![CDATA[Suite à mon quickstart Django, me revoici avec quelques astuces pour continuer.
Pour tester/développer avec Django, je rappelle qu&#8217;il vaut mieux utiliser le serveur de dev intégré, puis passer à Apache, nginx ou autre pour la production par la suite.
Il est important de lire pour commencer les principes de la philosophie Django ainsi que le &#8216;django coding style&#8217;
Ne [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-396" title="tips" src="http://blog.revolunet.com/wp-content/uploads/2009/12/tips.jpg" alt="tips" width="150" height="152" />Suite à mon <a href="http://blog.revolunet.com/index.php/general/bien-demarrer-avec-django" target="_blank">quickstart Django</a>, me revoici avec quelques astuces pour continuer.</p>
<p>Pour tester/développer avec Django, je rappelle qu&#8217;il vaut mieux utiliser le serveur de dev intégré, puis passer à Apache, nginx ou autre pour la production par la suite.</p>
<p>Il est important de lire pour commencer les principes de la <strong><a href="http://docs.djangoproject.com/en/dev/misc/design-philosophies/" target="_blank">philosophie Django</a> </strong>ainsi que le <a href="http://docs.djangoproject.com/en/dev/internals/contributing/#coding-style" target="_blank">&#8216;django coding style&#8217;</a></p>
<p><strong>Ne hardcodez pas vos paths</strong></p>
<ul>
<li>dans votre settings.py :</li>
<li>
<div class="codesnip-container" >BASE_DIR = os.path.dirname(__file__)</div>
</li>
<li>utilisez ensuite os.path.join avec settings.BASE_DIR ailleurs si besoin</li>
<li>Pour importer les settings de votre projet, utilisez toujours
<div class="codesnip-container" >from django.conf import settings</div>
</li>
</ul>
<p><strong>Utilisez un fichier local_settings.py</strong></p>
<ul>
<li>Créez un fichier local_settings.py qui contiendra uniquement les settings relatifs au déploiment de votre application : settings de base de données, smtp, debug&#8230; Vous n&#8217;aurez plus que celui la à modifier pour un nouveau déploiement.</li>
</ul>
<p><strong>Mettre en production avec Apache</strong></p>
<ul>
<li>Pour une installation classique avec <strong>Apache</strong>, utilisez de préférence <strong><a href="http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango" target="_blank">mod_wsgi</a>. <span style="color: #ff0000;">N&#8217;utilisez pas le serveur de dev intégré en production!</span></strong></li>
</ul>
<p><strong>Debug AJAX plus pratique</strong></p>
<ul>
<li>Si vous faites de l&#8217;Ajax, utilisez <strong><a href="https://addons.mozilla.org/fr/firefox/addon/1843" target="_blank">Firebug</a> et le middleware </strong><a href="http://www.djangosnippets.org/snippets/650/" target="_blank"><strong>AJAXSimpleExceptionResponse</strong></a></li>
</ul>
<p><strong>Queysets : filters et excludes dynamiques</strong></p>
<ul>
<li>Utilisez les dictionnaires pour filtrer dynamiquement vos querysets :</li>
</ul>
<div class="codesnip-container" >filtres = {}<br />
filtres['date__gte'] = datetime.datetime.today() &#8211; datetime.timedelta(dasy=7)<br />
filtres['titre__icontains'] = &#8216;python&#8217;<br />
excludes={}<br />
excludes['epuise'] = True<br />
qs = model.Livres.objects.exclude(**excludes).filter(**filtres)</div>
<p><strong>Créez des applications modulaires</strong></p>
<ul>
<li>Placez vos app dans un sous dossier &#8216;apps&#8217;</li>
<li>Utiliser des objets génériques : le <a href="http://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/" target="_blank">ContentType framework</a></li>
</ul>
<p><strong>Utilisez un script pour mettre à jour vos modèles</strong></p>
<ul>
<li>Django ne gérant pas nativement les ALTER sur votre base de données, vous devez sauvegarder (manage.py dumpdata), reset votre base (manage.py reset) puis recréer votre base (manage.py syncdb) et recharger les données (manage.py loaddata).</li>
<li>Utilisez plutot un <a href="http://www.chrisdpratt.com/2008/02/27/a-django-snippet-to-refresh-your-database/" target="_blank">script qui automatisera cette tache</a></li>
</ul>
<p><strong>Utilisez des décorateurs dans vos vues</strong></p>
<ul>
<li><strong>@login_required </strong>pour restreindre la vue aux utilisateurs loggés</li>
<li><strong>@user_passes_test(lambda u: u.has_perm(&#8217;polls.can_vote&#8217;)) </strong>pour restreindre la vue selon un test particulier</li>
<li>créez vos propres décorateurs</li>
</ul>
<p><strong>Ne définissez qu&#8217;une fois vos urls</strong></p>
<ul>
<li>Utilisez les <a href="{% url arch-summary 1945 %}" target="_blank">named-urls</a> pour ne plus harcoder vos urls
<ul>
<li>Dans urls.py :  
<div class="codesnip-container" >(r&#8217;^articles/list/(\d)+&#8217;, apps.main.list, name=&#8221;list-view&#8221;)</div>
</li>
<li>Dans une vue :
<div class="codesnip-container" >return HttpResponseRedirect(reverse(&#8217;list-view&#8217;, args=[2007]))</div>
</li>
<li>Dans un template :
<div class="codesnip-container" >&lt;a href=&#8221;{% url list-view 2007 %}&#8221;&gt;ma vue&lt;/a&gt;</div>
</li>
</ul>
</li>
<li>Utilisez <a href="http://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.get_absolute_url" target="_blank">get_absolute_url()</a> sur vos modèles pour affecter une url à chacun de vos objets</li>
</ul>
<p><strong>Des questions que vous vous posez surement :</strong></p>
<ul>
<li><a href="http://www.b-list.org/weblog/2006/jun/28/django-tips-difference-between-blank-and-null/" target="_blank">La différence entre null et blank</a> dans vos modèles</li>
<li>Comment toujours passer des variables à mes templates : les <a href="http://docs.djangoproject.com/en/dev/ref/templates/api/#id1" target="_blank">template contexts</a></li>
</ul>
<p><strong>De bons examples de coding-styles : </strong></p>
<ul>
<li><a href="http://code.google.com/p/django-basic-apps/" target="_blank">http://code.google.com/p/django-basic-apps/</a></li>
<li><a href="http://groups.google.com/group/django-hotclub" target="_blank">http://groups.google.com/group/django-hotclub</a></li>
</ul>
<p><strong>Différents cas de figures sur les formulaires Django</strong> : <a href="http://uswaretech.com/blog/2010/01/doing-things-with-django-forms/">http://uswaretech.com/blog/2010/01/doing-things-with-django-forms/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.revolunet.com/index.php/developpement/astuces-django/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Bien démarrer avec django</title>
		<link>http://blog.revolunet.com/index.php/general/bien-demarrer-avec-django</link>
		<comments>http://blog.revolunet.com/index.php/general/bien-demarrer-avec-django#comments</comments>
		<pubDate>Wed, 02 Dec 2009 11:21:53 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[developpement]]></category>
		<category><![CDATA[django]]></category>

		<guid isPermaLink="false">http://blog.revolunet.com/?p=381</guid>
		<description><![CDATA[Cela fait maintenant presque deux ans que j&#8217;utilise intensivement le framework Django pour toutes mes applications web, et j&#8217;ai enfin réuni assez d&#8217;éléments pour pouvoir vous livrer un petit &#8216;QuickStart&#8217; qui vous permettra de démarrer rapidement.
Contrairement à d&#8217;autres frameworks web, Django n&#8217;est pas orienté CMS ou HTML. Vous pouvez tout autant créer un site HTML/Ajax, une [...]]]></description>
			<content:encoded><![CDATA[<p>Cela fait maintenant presque deux ans que j&#8217;utilise intensivement le framework <a href="http://www.djangoproject.com/" target="_blank">Django</a> pour toutes mes applications web, et j&#8217;ai enfin réuni assez d&#8217;éléments pour pouvoir vous livrer un petit &#8216;QuickStart&#8217; qui vous permettra de démarrer rapidement.</p>
<p>Contrairement à d&#8217;<a href="http://drupal.org/" target="_blank">autres</a> <a href="http://www.zope.org/" target="_blank">frameworks</a> <a href="http://www.symfony-project.org/doc/1_4/" target="_blank">web</a>, Django n&#8217;est pas orienté CMS ou HTML. Vous pouvez tout autant créer un site HTML/Ajax, une API RESTFUL http ou une application en ligne de commande.</p>
<p>Django permet de coder toute la partie serveur de votre application, mais pour la partie &#8216;client&#8217;, c.a.d. le HTML par exemple, vous devrez vous débrouiller tout seul ou utiliser un autre framework, <a href="http://jquery.com/" target="_blank">jQuery</a> par exemple, ou <a href="http://extjs.com/" target="_blank">ExtJs</a>.</p>
<p><img class="alignleft size-full wp-image-389" title="django" src="http://blog.revolunet.com/wp-content/uploads/2009/12/django.jpg" alt="django" width="120" height="177" /></p>
<p style="padding-left: 120px;"><strong> Pourquoi Django ? </strong></p>
<p style="padding-left: 120px;">Open Source<br />
Portable<br />
Langage Python<br />
Prototypage rapide<br />
Evolutivité<br />
Abstration <a href="http://fr.wikipedia.org/wiki/Mapping_objet-relationnel" target="_blank">ORM<br />
</a> Supporté par <a href="http://fr.wikipedia.org/wiki/Google_App_Engine" target="_blank">Google AppEngine</a> (avec restrictions)<br />
Excellente <a href="http://docs.djangoproject.com/en/dev/" target="_blank">documentation</a></p>
<p><strong>Fonctionnalités principales :</strong></p>
<ul>
<li><strong>ORM :</strong> permet une abstraction de la base de données et du SQL, ce qui fait que vos applications peuvent tourner sur : SQLlite, MySQL, SQLserver, Oracle, PostGres&#8230;</li>
<li><strong>Admin automatique : </strong>une fois vos modèles définis, ils sont de suite accessible dans l&#8217;interface d&#8217;admin automatique, et vous pouvez toute de suite créer objets</li>
<li><strong>Templates : </strong>une gestion des templates très poussée, avec gestion des héritages, des filtres et &#8216;customs tags&#8217;.</li>
<li><strong>Shell intégré : </strong>Tout votre code est également accessible directement depuis un shell intégré</li>
<li><strong>Gestion des utilisateurs : </strong>Toute la partie utilisateurs, comptes, login, sécurité et permissions est déjà disponible sans efforts</li>
</ul>
<p><strong>Inconvénients :</strong></p>
<ul>
<li>Peu d&#8217;hébergeurs mais cela évolue : <a href="http://code.djangoproject.com/wiki/DjangoFriendlyWebHosts">http://code.djangoproject.com/wiki/DjangoFriendlyWebHosts</a></li>
<li>C&#8217;est surtout  un avantage, mais le projet évoluant très vite, vous devrez coder avec et pour une version spécifique de Django. Et vous ne mettrez à jour django pour tel projet seulement après avoir consulté cette page : <a href="http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges">http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges</a></li>
</ul>
<p>A noter que Django est une librairie python, vous pouvez n&#8217;utiliser que les fonctions dont vous avez besoin, même en &#8217;standalone&#8217;  (hors du web).  Et vous pouvez tout modifier, étendre et améliorer à souhait.</p>
<p>La première chose à faire avant de se lancer dans Django est déjà de connaitre un minimum le langage python et sa &#8216;magie&#8217;. Le livre &#8216;<a href="http://openbookproject.net//thinkCSpy/" target="_blank">Think like a computer scientist</a>&#8216; est à lire, <a href="http://hetland.org/writing/instant-python.html" target="_blank">Instant Python</a> pour les préssés, et &#8220;<a href="http://www.swaroopch.com/notes/Python_fr:Table_des_Mati%C3%A8res" target="_blank">A byte of python</a>&#8221; (en francais).</p>
<h2><strong>C&#8217;est parti</strong></h2>
<p>Installez <a href="http://python.org/download/" target="_blank">python </a>(2.5 ou 2.6) sur votre machine, et récupérez la <a href="http://www.djangoproject.com/download/" target="_blank">dernière version de Django</a>. Le repertoire &#8216;django&#8217; de cette archive doit se trouver dans le dossier &#8216;lib/site-packages&#8217; de votre installation de Python. Si vous souhaitez utiliser MySQL comme serveur, installez <a href="http://sourceforge.net/projects/mysql-python/" target="_blank">python-mysqldb</a>. Sinon, SQLlite fera très bien l&#8217;affaire pour démarrer !</p>
<p>Pour tester si votre installation de python/django est correcte :</p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 272px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">juju@devserver:/var/www/django$ python</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 272px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Python 2.5.2 (r252:60911, Jul 31 2008, 17:28:52)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 272px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 272px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Type &#8220;help&#8221;, &#8220;copyright&#8221;, &#8220;credits&#8221; or &#8220;license&#8221; for more information.</div>
<div class="codesnip-container" >juju@xxxxxxx:/home/juju$ python<br />
Python 2.5.2 (r252:60911, Jul 31 2008, 17:28:52)<br />
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2<br />
Type &#8220;help&#8221;, &#8220;copyright&#8221;, &#8220;credits&#8221; or &#8220;license&#8221; for more information.<br />
&gt;&gt;&gt;import django<br />
&gt;&gt;&gt;print django.VERSION<br />
(1, 0, 2, &#8216;final&#8217;, 0)<br />
&gt;&gt;&gt;</div>
<p>Si vous avez une erreur lors de l&#8217;import, alors votre dossier &#8216;django&#8217; n&#8217;est pas dans votre dossier python\lib\site-packages, vérifiez.</p>
<p>Si l&#8217;install est correcte, alors vous pouvez créer votre premier projet django.</p>
<p><strong>Exemple sur windows :</strong></p>
<p>Ouvrez un shell, et placez vous dans votre dossier de travail, puis lancez la commande django-admin.py startproject</p>
<div class="codesnip-container" >cd c:\dev\django<br />
c:\dev\django&gt;c:\Python25\lib\site-packages\django\bin\django-admin.py startproject projet1</div>
<p>Un dossier &#8216;projet1&#8242; a été crée et contient les fichier de base :</p>
<ul>
<li><strong>settings.py :</strong> configuration du projt, base de données, emails&#8230;</li>
<li><strong>urls.py : </strong>la configuration des urls de votre projet</li>
<li><strong>manage.py : </strong>la commande qui permet de lancer le serveur, mettre a jour les bases et effectuer des opérations de maintenance.</li>
<li><strong>__init__.py :</strong> ce fichier permet simplement à Python d&#8217;interpréter le dossier en tant que &#8216;module&#8217;</li>
</ul>
<p>Pour développer un projet Django, utilisez le &#8217;serveur de dev&#8217; intégré (commande manage.py runserver), mais pour la production, vous devrez mettre en place <a href="http://code.djangoproject.com/wiki/django_apache_and_mod_wsgi" target="_blank">Apache+WSGI</a>, <a href="http://www.alrond.com/en/2007/mar/01/start-django-with-nginx/" target="_blank">Nginx</a> ou <a href="http://code.djangoproject.com/wiki/ServerArrangements" target="_blank">un autre serveur</a>.</p>
<p>Lancez le serveur pour vérifier que votre projet est bien crée :</p>
<div class="codesnip-container" >cd c:\dev\django<br />
c:\dev\django&gt;manage.py runserver<br />
Validating models&#8230;<br />
0 errors found<br />
Django version 1.0-alpha-SVN-8225, using settings &#8216;projet1.settings&#8217;<br />
Development server is running at http://127.0.0.1:8000/<br />
Quit the server with CTRL-BREAK.</div>
<p>Maintenant vous pouvez ouvrir votre browser à cette adresse : <a href="http://127.0.0.1:8000/" target="_blank">http://127.0.0.1:8000/</a></p>
<p>Modifiez le fichier settings.py, puis suivez le <a href="http://docs.django-fr.org/intro/tutorial01.html#creation-des-modeles" target="_blank">premier tutorial</a> pour commencer à faire joujou.</p>
<p>Je reviens prochainement  pour <a href="http://blog.revolunet.com/index.php/developpement/astuces-django">la suite</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.revolunet.com/index.php/general/bien-demarrer-avec-django/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WordPress hacked &amp; spam injections</title>
		<link>http://blog.revolunet.com/index.php/general/wordpress-hacked-spam-injections</link>
		<comments>http://blog.revolunet.com/index.php/general/wordpress-hacked-spam-injections#comments</comments>
		<pubDate>Mon, 19 May 2008 19:52:52 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[actu informatique]]></category>
		<category><![CDATA[developpement]]></category>

		<guid isPermaLink="false">http://blog.revolunet.com/index.php/general/wordpress-hacked-spam-injections</guid>
		<description><![CDATA[Les spammers n&#8217;ont décidément plus de limite dans leur imagination   C&#8217;est ce que j&#8217;ai découvert en éditant un de mes articles sur ce blog. En regardant de près le code d&#8217;un de mes posts, je me suis rendu compte qu&#8217;a la fin du post, il y avait du spam ajouté en toute discretion&#8230;
Le spammer [...]]]></description>
			<content:encoded><![CDATA[<p>Les spammers n&#8217;ont décidément plus de limite dans leur imagination <img src='http://blog.revolunet.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  C&#8217;est ce que j&#8217;ai découvert en éditant un de mes articles sur ce blog. En regardant de près le code d&#8217;un de mes posts, je me suis rendu compte qu&#8217;a la fin du post, il y avait du spam ajouté en toute discretion&#8230;</p>
<p>Le spammer comence par injecter quelques tags :
<div class="codesnip-container" >&lt;!&#8211;c47fb25734eb9xxxxd6ece85fbe4e7a&#8211;&gt;&lt;!&#8211;88db79567a32a479fxxx69eff41d0&#8211;&gt;</div>
<p> puis insère une div cachée, non visible dans un navigateur :
<div class="codesnip-container" >;&lt;div id=&#8221;wp_internal&#8221; style=&#8221;position: absolute; left: -9112px&#8221;&gt;</div>
<p> puis insère tout un tas de liens sur le vi4gr4 et compagnie&#8230; Ceci est possible grâce à l&#8217;exploitation d&#8217;une <a href="http://secunia.com/search/?search=wordpress">faille de sécurité dans WordPress</a>, qui permet au hacker de se créer facilement un compte administrateur. Cette faille a depuis été corrigée d&#8217;ou l&#8217;importance de toujours <a href="http://codex.wordpress.org/fr:Mise_%C3%A0_jour" target="_blank">bien mettre à jour wordpress </a>et tout logiciel en général.</p>
<p>Si en plus le serveur est mal configuré, le hacker peut alors prendre le controle total de la machine en uploadant le <a onclick="alert('Non%20quand%20meme%20pas%20;')" href="#">parfait kit du pirate PHP</a>. Un outil de crackage a apparemment été développé pour automatiser la tache, polluer  à la chaine des milliers de blogs, certainement pour longtemps, et ainsi gonfler au maximum la popularité des sites cibles aux yeux des moteurs de recherche.</p>
<p>L&#8217;origine de l&#8217;attaque provient apparemment de Pologne et Russie. Le resultat de cette attaque a engendré un blacklistage de l&#8217;index de google et j&#8217;ai donc crée un script Python qui répare les dégats en supprimant les spams :</p>
<div class="codesnip-container" >
<div class="codesnip"><span class="kw1">import</span> <span class="kw3">re</span><br />
<span class="kw1">import</span> MySQLdb<br />
<span class="co1">#example spam tags to remove :</span><br />
<span class="co1"># &#8230;&amp;lt;!&#8211;1f195247aee1eba914f252716a78efba&#8211;&amp;gt;&amp;lt;!&#8211;b845738c6a171d114ceaa35493a4f0dc&#8211;&amp;gt;&amp;lt;div id=wp_internal style=position:absolute;left:-9112px&amp;gt;&amp;lt;a href=http://www.eeeeee/zefzef/wp-content/themes/default/zefezff/eeeeee.html&amp;gt;&#8230; </span><br />
&nbsp;</div>
</div>
<div class="codesnip-container" >
<div class="codesnip">db = MySQLdb.<span class="me1">connect</span><span class="br0">&#40;</span>host=<span class="st0">&#8220;192.168.0.1&#8243;</span>, <span class="kw3">user</span>=<span class="st0">&#8220;wp&#8221;</span>, passwd=<span class="st0">&#8220;passwp&#8221;</span>, db=<span class="st0">&#8220;wordpress_bdd&#8221;</span><span class="br0">&#41;</span><br />
cursor=db.<span class="me1">cursor</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
cursor.<span class="me1">execute</span><span class="br0">&#40;</span><span class="st0">&#8220;SELECT ID, POST_CONTENT FROM wp_posts ORDER BY ID DESC&#8221;</span><span class="br0">&#41;</span><br />
posts = cursor.<span class="me1">fetchall</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
log=<span class="br0">&#91;</span><span class="br0">&#93;</span><br />
<span class="kw1">for</span> post <span class="kw1">in</span> posts:<br />
    parts = <span class="kw3">re</span>.<span class="me1">split</span><span class="br0">&#40;</span>r<span class="st0">&#8220;&amp;lt;<span class="es0">\!</span>&#8211;<span class="es0">\w</span>{32}&#8211;&amp;gt;&#8221;</span>, post<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
    <span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span>parts<span class="br0">&#41;</span>&amp;gt;<span class="nu0">1</span>:<br />
        clean_post = parts<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="st0">&#8220;&#8216;&#8221;</span>, <span class="st0">&#8220;&#8221;&#8221;</span><span class="br0">&#41;</span><br />
        sql = <span class="st0">&#8220;update wp_posts set POST_CONTENT=&#8217;%s&#8217; where ID=%s;&#8221;</span> % <span class="br0">&#40;</span>clean_post, post<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
        log.<span class="me1">append</span><span class="br0">&#40;</span>sql<span class="br0">&#41;</span><br />
        cursor.<span class="me1">execute</span><span class="br0">&#40;</span>sql<span class="br0">&#41;</span><br />
        <span class="kw1">print</span> <span class="st0">&#8220;updating post %s&#8221;</span> % post<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><br />
db.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
f=<span class="kw2">open</span><span class="br0">&#40;</span><span class="st0">&#8220;wp_out.sql&#8221;</span>, <span class="st0">&#8220;w&#8221;</span><span class="br0">&#41;</span><br />
f.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">&#8220;<span class="es0">\n</span>&#8220;</span>.<span class="me1">join</span><span class="br0">&#40;</span>log<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</div>
<p><strong><span style="color: #ff0000;">Attention à bien sauvegarder votre base de données avant d&#8217;executer ce script ! Si vous ne comprennez pas le script, ne l&#8217;executez pas !</span></strong></p>
<p>J&#8217;attends impatiemment le retour du traffic si google veut bien me réindexer !</p>
<p><strong>EDIT :</strong>Deux jours après application du script + demande de réexamen dans <a href="https://www.google.com/webmasters/tools">Google webmaster tools</a> le traffic est revenu à la normale&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.revolunet.com/index.php/general/wordpress-hacked-spam-injections/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Google AppEngine revolutionne le développement web</title>
		<link>http://blog.revolunet.com/index.php/general/google-revolutionne-le-developpement-web</link>
		<comments>http://blog.revolunet.com/index.php/general/google-revolutionne-le-developpement-web#comments</comments>
		<pubDate>Thu, 10 Apr 2008 09:35:18 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[actu informatique]]></category>
		<category><![CDATA[developpement]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.revolunet.com/index.php/general/google-revolutionne-le-developpement-web</guid>
		<description><![CDATA[Durant ces 10 dernières années, Google a révolutionné la recherche, le e-marketing, la cartographie et bien d&#8217;autres services à destination des usagers. Depuis quelques temps, Google s&#8217;est aussi investit dans l&#8217;open source, notamment grâce à code.google.com qui propose de nombreuses librairies open source pour les développeurs, ainsi que des espaces gratuits de gestion de projets a [...]]]></description>
			<content:encoded><![CDATA[<p>Durant ces 10 dernières années, Google a révolutionné la recherche, le e-marketing, la cartographie et bien d&#8217;autres services à destination des usagers. Depuis quelques temps, Google s&#8217;est aussi investit dans l&#8217;open source, notamment grâce à <a target="_blank" href="http://code.google.com">code.google.com</a> qui propose de nombreuses librairies open source pour les développeurs, ainsi que des espaces gratuits de gestion de projets a la <a target="_blank" href="http://www.sourceforge.net">sourceforge</a>.</p>
<p>Aujourd&#8217;hui, Google lance <a target="_blank" href="http://code.google.com/appengine">Google AppEngine</a>, un service à destination des développeurs web, qui va leur faciliter grandement le développement d&#8217;applications web, en leur permettant de se concentrer sur la partie la plus fun de leur metier : le code lui-même. Et tout cela gratuitement (pour l&#8217;instant).</p>
<p>Google AppEngine est en effet un framework qui permet d&#8217;écrire très facilement des applications en Python, sans se soucier ni de la base de données, ni de l&#8217;hebergement, ni de l&#8217;administration système, ni des sauvegardes. Pour ceux qui ne connaissent pas bien Python c&#8217;est un langage très haut niveau, très lisible, très logique, et <a target="_blank" href="http://mail.python.org/pipermail/python-dev/2004-April/044002.html">très performant</a>; Google l&#8217;utilise à de nombreux niveaux de son architecture et a d&#8217;ailleurs <a target="_blank" href="http://blog.revolunet.com/index.php/general/guido-van-rossum-embauche-par-google">embauché son créateur le fameux Guido Von Rossum</a> en 2005. Concrètement, vous définissez vos modèles de données, vos templates graphiques et votre code métier (facon <a target="_blank" href="http://fr.wikipedia.org/wiki/Mod%C3%A8le-Vue-Contr%C3%B4leur">MVC</a>), puis publiez très simplement votre projet directement sur la plate forme Google. Vous avez alors la puissance de Google entre vos doigts, et disposez d&#8217;une extraordinaire flexibilité et extensibilité de votre application, le tout de facon 100% transparente. Votre application est hebergée chez Google, et vos données reparties sur de nombreux serveurs à travers le monde ce qui vous garantit une haute disponibilité et de hautes performances quel que soit le volume de vos données et le traffic que vous générez.</p>
<p>Techniquement, Google vous propose un <a target="_blank" href="http://code.google.com/appengine/downloads.html">SDK</a> (dispo sur Windows, Mac, Linux) qui vous installe un environnement de développement similaire à la version en ligne de AppEngine . Ce framework est open source et basé sur le célèbre framework web en python <a target="_blank" href="http://www.djangoproject.com">Django</a> (Templates, DataModels&#8230;), <a target="_blank" href="http://pythonpaste.org/webob">Webob</a> (Modele objet request/response) et sur plusieurs API fournies par Google pour nous faciliter la vie : <a target="_blank" href="http://code.google.com/appengine/docs/datastore/">Datastore API</a> pour la base de données (basé sur la technologie BigTable de Google), <a target="_blank" href="http://code.google.com/appengine/docs/users/">Users API</a> pour la gestion des utilisateurs et <a target="_blank" href="http://code.google.com/appengine/docs/">autres joyeusetés</a>&#8230; Bien sûr vous pouvez ajouter toutes les librairies Python que vous souhaitez à votre projet.</p>
<p>Ce service n&#8217;est pas destiné aux applications professionnelles car vous êtes trop dépendant de Google et n&#8217;avez aucun contrôle sur de nombreux points (notamment la base de données ou les librairies bas niveau disponibles) mais ce service va certainement faciliter le développement de nombreuses applications web, sociales (ou pas), web 2.0 (ou pas). Ma grand mere va peut etre enfin pouvoir coder l&#8217;application web de bridge dont elle rève depuis toujours et que je n&#8217;ai jamais eu le temps de faire pour son Noël ;)</p>
<p>Le service est encore en beta, pas encore ouvert au quidam pendant une phase de tests de plusieurs mois mais on peut d&#8217;ores et deja installer le SDK et tester la plateforme en local pour faire joujou. Et on s&#8217;amuse. A terme Google proposera surement à la maniere <a href="http://aws.amazon.com/s3">d&#8217;Amazon S3</a> de la location de ressources si vous avez besoin de plus de ressources que ce qui vous est offert.</p>
<p>Démonstrations videos : <a href="http://youtube.com/watch?v=tcbpTQXNwac">http://youtube.com/watch?v=tcbpTQXNwac</a></p>
<p>Le SDK : <a href="http://code.google.com/appengine/downloads.html">http://code.google.com/appengine/downloads.html</a></p>
<p>La Documentation : <a href="http://code.google.com/appengine/docs/">http://code.google.com/appengine/docs/</a></p>
<p>Le groupe de discussion : <a href="http://groups.google.com/group/google-appengine?lnk=sg">http://groups.google.com/group/google-appengine?lnk=sg</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.revolunet.com/index.php/general/google-revolutionne-le-developpement-web/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>test du e65, nouvelle bombe de chez Nokia</title>
		<link>http://blog.revolunet.com/index.php/general/test-du-e65-nouvelle-bombe-de-chez-nokia</link>
		<comments>http://blog.revolunet.com/index.php/general/test-du-e65-nouvelle-bombe-de-chez-nokia#comments</comments>
		<pubDate>Fri, 11 May 2007 09:05:48 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[actu informatique]]></category>
		<category><![CDATA[geek style]]></category>
		<category><![CDATA[hardware]]></category>

		<guid isPermaLink="false">http://blog.revolunet.com/index.php/general/test-du-e65-nouvelle-bombe-de-chez-nokia</guid>
		<description><![CDATA[


Cela faisait un moment que je pensais m&#8217;offrir le Nokia N80 ou le N95 mais c&#8217;etait sans compter la sortie récente du E65. Discret et élégant, ce téléphone est techniquement au top de ce qui se fait actuellement, pour un prix, avec abonnement (1 an SFR), de 69 € seulement !!Basé sur l&#8217;excellent système d&#8217;exploitation [...]]]></description>
			<content:encoded><![CDATA[<table>
<tr>
<td><img alt="nokia-e651.jpg" style="width: 207px; height: 176px" title="nokia-e651.jpg" id="image238" src="http://blog.revolunet.com/wp-content/uploads/2007/05/nokia-e651.jpg" /></td>
<td style="font-size: 14px">Cela faisait un moment que je pensais m&#8217;offrir le Nokia N80 ou le N95 mais c&#8217;etait sans compter la sortie récente du E65. Discret et élégant, ce téléphone est techniquement au top de ce qui se fait actuellement, pour un prix, avec abonnement (1 an SFR), de 69 € seulement !!Basé sur l&#8217;excellent système d&#8217;exploitation Symbian version 9.1 (alors que le N80 utilise une version plus ancienne), le e65 propose nativement le WiFi et la téléphonie SIP, ce qui permet de faire de grosses économies sur sa facture téléphonique (par exemple en passant par son compte Freebox pour appeller).</td>
</tr>
</table>
<p>La navigation est rapide, on peut surfer sur Internet en WiFi, streamer des flux Audio et Video (format RealPlayer), lire des mp3 sur sa carte MicroSD, visualiser des PDF, Word, Excel et meme des animations Flash&#8230; On peut bien sur recevoir et envoyer des mails (POP et IMAP) via autant de comptes que l&#8217;on souhaite. Grace à Google Maps For Mobile, vous pouvez consulter les cartes, images satellite et itinéraires dans le monde entier. Vous pouvez également le connecter à un module GPS Bluetooth externe, ce qui vous permettra d&#8217;ajouter toutes les fonctions classiques d&#8217;un systeme GPS (sans voix). L&#8217;appareil n&#8217;est qu&#8217;un 2 mégapixels mais bon c&#8217;est un smartphone avant tout.</p>
<p>Comme le téléphone tourne sous Symbian, vous pourrez trouver sur Internet une multitude de jeux et programmes gratuits ou pas et les installer très facilement (attention aux paramètres de sécurité). Si vous êtes programmeur ou avez envie de bidouiller, vous pourrez facilement installer le support du fabuleux language Python et la <a target="_blank" href="http://people.csail.mit.edu/kapu/symbian/python.html">console Python par Bluetooth</a>, une excellente innovation pour les développeurs. En effet, vous pourrez coder directement sur votre mobile depuis votre PC !! Ensuite, vous ferez comme beaucoup de développeurs Symbian, vous mettrez votre code à disposition de la communauté sur <a href="http://symbianos.org/">http://symbianos.org/</a> par exemple.</p>
<p>Pour ceux qui sont inscrits au programme de WiFi communautaire FON, un programme permet de gérer automatiquement les connexions aux bornes FON et ainsi de pouvoir téléphoner via SIP et surfer gratuitement dans de nombreux endroits&#8230; téléchargez le ici : <a href="http://www.fon.com/fr/download">http://www.fon.com/fr/download</a>. Et si vous n&#8217;etes pas encore un Fonero, achetez votre fon sur fr.fon.com ! Il me reste 3 invitations, contactez moi ici si vous en voulez une (20€ TTC) sur contact at revolunet.com</p>
<p>Si vous avez actuellement un Nokia, un outil de synchronisation Bluetooth ou Infrarouge est fourni, qui permet en quelques minutes de synchroniser les données entre vos deux mobiles. Sinon, vous pouvez utiliser le service online <a target="_blank" href="https://www.mobical.net">Mobical</a> qui se chargera de synchroniser sur deux appareils différents.</p>
<p>Alors n&#8217;hésitez plus, technophile ou pas, foncez sur ce superbe appareil qui ne vous decevra surement pas !!</p>
<p>Et si vous avez des astuces à partager ou des questions, n&#8217;hesitez pas, les commentaires sont ouverts <img src='http://blog.revolunet.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><strong>Configuration nécessaire pour téléphonie SIP via freephonie :</strong></p>
<p>Suivez le guide pour les nokia e-series à cette adresse (wiki freephonie) : <a href="http://www.freephonie.org/doku/tutoriel:seriee">http://www.freephonie.org/doku/tutoriel:seriee</a> <strong>mais </strong>ne spécifiez <strong>PAS </strong>de serveur Proxy&#8230; Connectez vous à votre point d&#8217;accès WiFi, puis dans le menu &#8216;Connectivité, Téléphonie Internet&#8217;, vérifiez que vous êtes bien connecté !</p>
<p><strong>(NB : Nous n&#8217;avons pas acces pour l&#8217;instant aux points d&#8217;accès Freephonie, on peut seulement utiliser des point d&#8217;accès pour lesquels nous avons les clés)</strong></p>
<p><strong>EDIT 05/12/07 : Free a activé le telechargement des certificats SIP pour tout telephone dans son interface !!!</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.revolunet.com/index.php/general/test-du-e65-nouvelle-bombe-de-chez-nokia/feed</wfw:commentRss>
		<slash:comments>93</slash:comments>
		</item>
		<item>
		<title>des PDF dynamiques facilement</title>
		<link>http://blog.revolunet.com/index.php/general/des-pdf-dynamiques-facilement</link>
		<comments>http://blog.revolunet.com/index.php/general/des-pdf-dynamiques-facilement#comments</comments>
		<pubDate>Sun, 18 Mar 2007 22:32:04 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[developpement]]></category>

		<guid isPermaLink="false">http://blog.revolunet.com/index.php/general/des-pdf-dynamiques-facilement</guid>
		<description><![CDATA[Voici une petite astuce pour générer à la volée des PDF dynamiques du style formulaire à remplir.
Il s&#8217;agit de générer des PDF à parti d &#8216;un modèle source avec des données contenues dans un fichier FDF (Forms Data Format).  Ce contenu, vous le générez dynamiquement comme le souhaitez, en python par exemple et en récupérant [...]]]></description>
			<content:encoded><![CDATA[<p>Voici une petite astuce pour générer à la volée des PDF dynamiques du style formulaire à remplir.</p>
<p>Il s&#8217;agit de générer des PDF à parti d &#8216;un modèle source avec des données contenues dans un fichier FDF (Forms Data Format).  Ce contenu, vous le générez dynamiquement comme le souhaitez, en python par exemple et en récupérant les infos d&#8217;une base de données.</p>
<p>Dans cette exemple, on créera un simple formulaire pré-rempli à imprimer, mais vous pouvez également créer un formulaire dynamique, que le client pourra remplir à l&#8217;écran directement (comme le declaration des impots sur internet) avec du javascript intégré.</p>
<ol>
<li>Préparez votre document PDF avec des champs nommés. Vous pouvez utiliser des textbox, des listbox, des checkbox, radios&#8230;.</li>
<li>Dans votre script qui pourra être appelé depuis une page web, créez un document FDF  puis utilisez l&#8217;excellent freeware <a href="http://www.accesspdf.com/pdftk/" target="_blank">pdftk</a> pour &#8216;merger&#8217; le PDF source et les données. Cet outil vous permettra de nombreuses manipulations de pdf : assemblage, extraction de pages, compression&#8230;</li>
<li>Exemples de fichiers FDF (data.fdf) : <a href="http://www.google.com/search?ie=UTF-8&#038;q=filetype%3afdf">http://www.google.com/search?ie=UTF-8&#038;q=filetype%3afdf</a></li>
<li>Script python pour générer le PDF avec pdftk :
<div class="codesnip-container" >import os<br />
os.system(&#8221;pdftk.exe source.pdf fill_form data.fdf output output.pdf flatten&#8221;)</div>
<p>je rajoute &#8216;flatten&#8217; pour supprimer les champs dans le pdf final</li>
<li>Magie, un PDF pré-rempli est généré</li>
</ol>
<p>Et voila, avec cette recette, vous pourrez générer de nombreux documents PDF très facilement <img src='http://blog.revolunet.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.revolunet.com/index.php/general/des-pdf-dynamiques-facilement/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python SideBar</title>
		<link>http://blog.revolunet.com/index.php/general/python-sidebar</link>
		<comments>http://blog.revolunet.com/index.php/general/python-sidebar#comments</comments>
		<pubDate>Tue, 24 Oct 2006 13:44:40 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[developpement]]></category>

		<guid isPermaLink="false">http://blog.revolunet.com/index.php/general/python-sidebar</guid>
		<description><![CDATA[Si vous developpez en Python, alors vous devez absolument installer cette sidebar pour FireFox !
Elle liste sous forme d&#8217;arbre la reference, la librairie, l&#8217;api C, les modules et même le tutorial
Et il y a aussi de quoi lancer une recherche sur notre site préféré : python.org
un must-have ! http://www.edgewall.org/python-sidebar/
]]></description>
			<content:encoded><![CDATA[<p>Si vous developpez en Python, alors vous devez absolument installer cette sidebar pour FireFox !</p>
<p>Elle liste sous forme d&#8217;arbre la reference, la librairie, l&#8217;api C, les modules et même le tutorial</p>
<p>Et il y a aussi de quoi lancer une recherche sur notre site préféré : python.org</p>
<p>un must-have ! <a href="http://www.edgewall.org/python-sidebar/">http://www.edgewall.org/python-sidebar/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.revolunet.com/index.php/general/python-sidebar/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Trier un tuple ou une liste de dictionnaires via une cl&#233;</title>
		<link>http://blog.revolunet.com/index.php/general/trier-un-tuple-ou-une-liste-de-dictionnaires-via-une-cle</link>
		<comments>http://blog.revolunet.com/index.php/general/trier-un-tuple-ou-une-liste-de-dictionnaires-via-une-cle#comments</comments>
		<pubDate>Mon, 03 Jul 2006 11:37:24 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.revolunet.com/index.php/general/trier-un-tuple-ou-une-liste-de-dictionnaires-via-une-cle</guid>
		<description><![CDATA[En Python, je veux trier une liste de dictionnaires par rapport &#224;  la valeur d&#8217;une des cl&#233;s. Pour cela, il est tr&#232;s pratique d&#8217;utiliser une fonction anonyme lambda.
Exemple :

MaListe = &#91;&#93;
Dico1 = &#123;&#8220;Pr&#38;eacute;nom&#8221;:&#8220;Julien&#8221;,&#8220;Succ&#38;egrave;s&#8221;:5,&#8220;Erreurs&#8221;:3&#125;
Dico2 = &#123;&#8220;Pr&#38;eacute;nom&#8221;:&#8220;C&#38;eacute;line&#8221;,&#8220;Succ&#38;egrave;s&#8221;:8,&#8220;Erreurs&#8221;:4&#125;
Dico3 = &#123;&#8220;Pr&#38;eacute;nom&#8221;:&#8220;J&#38;eacute;r&#38;ocirc;me&#8221;,&#8220;Succ&#38;egrave;s&#8221;:7,&#8220;Erreurs&#8221;:6&#125;
MaListe.append&#40;Dico1&#41;
MaListe.append&#40;Dico2&#41;
MaListe.append&#40;Dico3&#41;
# Si je veux trier par la colonne &#34;Succ&#38;egrave;s&#34; :
# en mode croissant :
MaListe.sort&#40;lambda x,y: cmp&#40;x&#91;&#8220;Succ&#38;egrave;s&#8221;&#93;,y&#91;&#8220;Succ&#38;egrave;s&#8221;&#93;&#41;&#41;
# en mode [...]]]></description>
			<content:encoded><![CDATA[<p>En <a target="_blank" href="http://www.Python.org">Python</a>, je veux trier une liste de dictionnaires par rapport &agrave;  la valeur d&#8217;une des cl&eacute;s. Pour cela, il est tr&egrave;s pratique d&#8217;utiliser une fonction anonyme lambda.</p>
<p>Exemple :</p>
<div class="codesnip-container" >
<div class="codesnip">MaListe = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
Dico1 = <span class="br0">&#123;</span><span class="st0">&#8220;Pr&amp;eacute;nom&#8221;</span>:<span class="st0">&#8220;Julien&#8221;</span>,<span class="st0">&#8220;Succ&amp;egrave;s&#8221;</span>:<span class="nu0">5</span>,<span class="st0">&#8220;Erreurs&#8221;</span>:<span class="nu0">3</span><span class="br0">&#125;</span><br />
Dico2 = <span class="br0">&#123;</span><span class="st0">&#8220;Pr&amp;eacute;nom&#8221;</span>:<span class="st0">&#8220;C&amp;eacute;line&#8221;</span>,<span class="st0">&#8220;Succ&amp;egrave;s&#8221;</span>:<span class="nu0">8</span>,<span class="st0">&#8220;Erreurs&#8221;</span>:<span class="nu0">4</span><span class="br0">&#125;</span><br />
Dico3 = <span class="br0">&#123;</span><span class="st0">&#8220;Pr&amp;eacute;nom&#8221;</span>:<span class="st0">&#8220;J&amp;eacute;r&amp;ocirc;me&#8221;</span>,<span class="st0">&#8220;Succ&amp;egrave;s&#8221;</span>:<span class="nu0">7</span>,<span class="st0">&#8220;Erreurs&#8221;</span>:<span class="nu0">6</span><span class="br0">&#125;</span><br />
MaListe.<span class="me1">append</span><span class="br0">&#40;</span>Dico1<span class="br0">&#41;</span><br />
MaListe.<span class="me1">append</span><span class="br0">&#40;</span>Dico2<span class="br0">&#41;</span><br />
MaListe.<span class="me1">append</span><span class="br0">&#40;</span>Dico3<span class="br0">&#41;</span></p>
<p><span class="co1"># Si je veux trier par la colonne &quot;Succ&amp;egrave;s&quot; :</span><br />
<span class="co1"># en mode croissant :</span><br />
MaListe.<span class="me1">sort</span><span class="br0">&#40;</span><span class="kw1">lambda</span> x,y: <span class="kw2">cmp</span><span class="br0">&#40;</span>x<span class="br0">&#91;</span><span class="st0">&#8220;Succ&amp;egrave;s&#8221;</span><span class="br0">&#93;</span>,y<span class="br0">&#91;</span><span class="st0">&#8220;Succ&amp;egrave;s&#8221;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<span class="co1"># en mode d&amp;eacute;croissant :</span><br />
MaListe.<span class="me1">sort</span><span class="br0">&#40;</span><span class="kw1">lambda</span> x,y: <span class="kw2">cmp</span><span class="br0">&#40;</span>y<span class="br0">&#91;</span><span class="st0">&#8220;Succ&amp;egrave;s&#8221;</span><span class="br0">&#93;</span>,x<span class="br0">&#91;</span><span class="st0">&#8220;Succ&amp;egrave;s&#8221;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</div>
<p>Et voil&agrave;  ! En une seule ligne de code, j&#8217;obtiens une liste tri&eacute;e par rapport &agrave;  une cl&eacute; de votre dictionnaire&#8230; sympa Python !</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.revolunet.com/index.php/general/trier-un-tuple-ou-une-liste-de-dictionnaires-via-une-cle/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python Email Grabber</title>
		<link>http://blog.revolunet.com/index.php/general/python-email-grabber</link>
		<comments>http://blog.revolunet.com/index.php/general/python-email-grabber#comments</comments>
		<pubDate>Tue, 20 Jun 2006 13:02:43 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.revolunet.com/index.php/general/python-email-grabber</guid>
		<description><![CDATA[Voici quelques lignes de Python qui vont vous permettre de r&#233;cup&#233;rer en quelques secondes tous les emails contenus dans un ou plusieurs fichiers. Ce code utilise le module re, d&#233;di&#233; aux expressions r&#233;guli&#232;res. On scanne un repertoire et on extrait tous les emails contenus dans chaque fichier.
Adaptez le code &#224;  vos besoins.

def readFile&#40;inFile&#41;:
# fonction [...]]]></description>
			<content:encoded><![CDATA[<p>Voici quelques lignes de Python qui vont vous permettre de r&eacute;cup&eacute;rer en quelques secondes tous les emails contenus dans un ou plusieurs fichiers. Ce code utilise le module <strong>re</strong>, d&eacute;di&eacute; aux expressions r&eacute;guli&egrave;res. On scanne un repertoire et on extrait tous les emails contenus dans chaque fichier.</p>
<p>Adaptez le code &agrave;  vos besoins.</p>
<div class="codesnip-container" >
<div class="codesnip"><span class="kw1">def</span> readFile<span class="br0">&#40;</span>inFile<span class="br0">&#41;</span>:<br />
<span class="co1"># fonction qui permet de lire le contenu d&#8217;un fichier</span><br />
f=<span class="kw2">open</span><span class="br0">&#40;</span>inFile,<span class="st0">&#8220;r&#8221;</span><span class="br0">&#41;</span><br />
contents=f.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw1">return</span> contents</p>
<p><span class="kw1">def</span> writeFile<span class="br0">&#40;</span>outFile,contents<span class="br0">&#41;</span>:<br />
<span class="co1"># fonction qui permet d&#8217;ecrire du contenu dans un fichier</span><br />
f=<span class="kw2">open</span><span class="br0">&#40;</span>outFile,<span class="st0">&#8220;w&#8221;</span><span class="br0">&#41;</span><br />
f.<span class="me1">write</span><span class="br0">&#40;</span>contents<span class="br0">&#41;</span><br />
f.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> getEmailsInFile<span class="br0">&#40;</span>inFile<span class="br0">&#41;</span>:<br />
<span class="co1"># permet de lire un fichier puis d&#8217;en extraire une liste d&#8217;emails</span><br />
contents = readFile<span class="br0">&#40;</span>inFile<span class="br0">&#41;</span><br />
<span class="kw1">return</span> getEmails<span class="br0">&#40;</span>contents<span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> getEmails<span class="br0">&#40;</span>contents<span class="br0">&#41;</span>:<br />
<span class="co1"># extrait tous les mails contenus dans une chaine</span><br />
<span class="kw1">import</span> <span class="kw3">re</span><br />
exprat=<span class="kw3">re</span>.<span class="kw2">compile</span><span class="br0">&#40;</span><span class="st0">&#8216;[0-9a-z.-]+[@][0-9a-z.-]+&#8217;</span><span class="br0">&#41;</span>&nbsp; &nbsp; &nbsp;<span class="co1"># la regexp qui detecte les emails</span><br />
mailz = exprat.<span class="me1">findall</span><span class="br0">&#40;</span>contents<span class="br0">&#41;</span>&nbsp; &nbsp; <span class="co1"># retourne une liste avec tous les resultats</span><br />
<span class="kw1">return</span> mailz</p>
<p><span class="kw1">import</span> <span class="kw3">os</span></p>
<p>rootPath = r<span class="st0">&#8220;c:RepertoireAAnalyser&#8221;</span> <span class="co1"># repertoire &amp;agrave;&nbsp; analyser</span><br />
lstEmails = <span class="br0">&#91;</span><span class="br0">&#93;</span>&nbsp; &nbsp;<span class="co1"># liste vide</span></p>
<p><span class="kw1">for</span> afile <span class="kw1">in</span> <span class="kw3">os</span>.<span class="me1">listdir</span><span class="br0">&#40;</span>rootPath<span class="br0">&#41;</span>:<br />
fullPath = <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">join</span><span class="br0">&#40;</span>rootPath,afile<span class="br0">&#41;</span><br />
<span class="kw1">if</span> <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">isfile</span><span class="br0">&#40;</span>fullPath<span class="br0">&#41;</span>:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># si fichier</span><br />
<span class="kw1">for</span> <span class="kw3">email</span> <span class="kw1">in</span> getEmailsInFile<span class="br0">&#40;</span>fullPath<span class="br0">&#41;</span>:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># detection emails</span><br />
<span class="kw1">if</span> <span class="kw3">email</span> <span class="kw1">not</span> <span class="kw1">in</span> lstEmails:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1"># verif doublons</span><br />
lstEmails.<span class="me1">append</span><span class="br0">&#40;</span><span class="kw3">email</span><span class="br0">&#41;</span></p>
<p><span class="kw1">print</span> <span class="st0">&#8220;%s emails trouv&amp;eacute;s&#8221;</span> % <span class="kw2">len</span><span class="br0">&#40;</span>lstEmails<span class="br0">&#41;</span>&nbsp; &nbsp; &nbsp; &nbsp;</p>
<p><span class="co1"># exporte la liste dans un fichier &#8216;Emails.csv&#8217;, les emails s&amp;eacute;par&amp;eacute;s par des retours &amp;agrave;&nbsp; la ligne (</span><br />
<span class="br0">&#41;</span><br />
writeFile<span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">join</span><span class="br0">&#40;</span>rootPath,<span class="st0">&#8220;Emails.csv&#8221;</span><span class="br0">&#41;</span>,<span class="st0">&#8220;<br />
&#8220;</span>.<span class="me1">join</span><span class="br0">&#40;</span>lstEmails<span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.revolunet.com/index.php/general/python-email-grabber/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

