Retrouvez tous les articles liés au tag Django via le
flux rss dédié à ce tag.
L'erreur bête et très frustrante du jour vient d'un petit formulaire qui permet de téléverser un fichier quelconque sur le serveur. Vous me direz, c'est la base du formulaire web avec des fichiers, et il ne devrait pas y avoir de soucis particuliers... sauf lorsque lesdits fichiers ont des accents dans le nom de fichier, et qu'une erreur aussi frustrante que difficile à analyser débarque avec ses gros sabots.
Alors, premier réflexe : chercher sur le net, entre Stack Overflow et le tracker de bug de django. Vous pourrez tomber sur ce genre de discussions : UnicodeEncodeError: 'ascii' codec can't encode character.
Cela donne déjà un premier aperçu d'où vient le problème, à savoir, une configuration de locale sur l'environnement serveur. Pour vous en dire plus, voici les symptômes auxquels j'ai été moi-même confrontés :
- le formulaire fonctionne avec le serveur de dev de django
- il ne fonctionne plus derrière apache/nginx/votre serveur web favori
- vous utilisez un serveur wsgi (du genre gunicorn) ou bien le
mod_wsgi d'apache
- seul les fichiers avec des caractères accentués (ou "spéciaux") font lever l'exception
La première "solution" qui est proposée, c'est que l'environnement serveur soit correctement configuré, avec, entre autre, une modification du fichier /etc/apache2/envvars. Personnellement, j'ai essayé, mais cela ne fonctionne pas.
Bref, que faire dans ces cas là ?
Comprendre et analyser le problème
Je ne suis pas un expert, mais voici ma démarche pour comprendre puis résoudre ce problème.
Tout d'abords, j'ai regardé la locale de la machine à l'aide de la commande locale, et j'ai obtenu ceci :
LANG=fr_FR.UTF-8
LANGUAGE=
LC_CTYPE="fr_FR.UTF-8"
LC_NUMERIC="fr_FR.UTF-8"
LC_TIME="fr_FR.UTF-8"
LC_COLLATE="fr_FR.UTF-8"
LC_MONETARY="fr_FR.UTF-8"
LC_MESSAGES="fr_FR.UTF-8"
LC_PAPER="fr_FR.UTF-8"
LC_NAME="fr_FR.UTF-8"
LC_ADDRESS="fr_FR.UTF-8"
LC_TELEPHONE="fr_FR.UTF-8"
LC_MEASUREMENT="fr_FR.UTF-8"
LC_IDENTIFICATION="fr_FR.UTF-8"
LC_ALL=
Ensuite, j'ai lancé l'interpréteur python, pour en savoir plus :
>>> import locale
>>> locale.getlocale()
(None, None)
>>> locale.getdefaultlocale()
('fr_FR', 'UTF-8')
Bon, je remercie ici mYk et linova sur IRC de m'avoir fait chercher dans ces directions, et de m'avoir proposé ensuite de vérifier la valeur de ces informations là dans le contexte de mon application django. J'ai donc affiché ces valeurs dans un template et voici les valeurs que j'ai obtenues avec le serveur de dev de django :
loc: (None, None)
loc_def: ('fr_FR', 'UTF-8')
Puis la même chose, mais avec gunicorn :
loc: (None, None)
loc_def: (None, None)
À partir de là, j'ai pu enfin comprendre le problème, et comment le résoudre. Merci à linova pour l'idée sur IRC.
Merci encore une fois au chan #djangocong sur freenode !
Résoudre le problème
J'utilise runnit pour gérer mes différentes applications servies par gunicorn, et j'ai donc des petits scripts (comme pour init.d), dans lesquels j'ai ajouté ceci :
export LC_ALL=fr_FR.UTF8
Et c'est tout. Oui, tout à fait, c'était juste ça : la locale n'était pas définie dans ce contexte très particulier, et pas dans un autre, ce qui explique tout mon problème avec ces foutus fichiers. J'ai redémarré les différentes applications, et je n'ai plus constaté de problèmes.
Alors, si vous aussi vous avez ce problème, je vous conseille de suivre la même démarche que moi : vérifiez vos locales, vérifiez vos locales via l'interpréteur python d'une part, puis dans le contexte de votre application plus spécifiquement.
Enfin, allez voir du côté du script de votre serveur, et voyez s'il n'y a pas quelque chose à faire avec.
Sur ma liste des choses à faire, il y avait cette migration concrète de mon site&blog vers Django 1.3. Il faut savoir que j'ai développé à l'origine avec la version 1.1, en ajoutant à l'occasion quelques petites choses de Django 1.2 lorsque j'ai mis à jour mon serveur.
Aujourd'hui, mes dernières applications sont développées avec Django 1.3, et il y a quelques petites choses en plus que j'apprécie bien. Je vous propose donc un retour d'expérience, avec un tour d'horizon de ce que j'ai modifié et eu à modifier.
Nommer les urls
Je n'avais pas touché à mon fichier urls.py depuis longtemps, et j'ai donc commencé par là : remettre certains trucs à plat, et rendre le tout plus propre et plus facile à maintenir.
Premier truc : utiliser la fonction url, qui permet entre autre chose de nommer ses urls, ce qui est très pratiques pour la suite, comme, par exemple, ne pas s'embêter à écrire des urls en dur dans les templates.
Exemple de template (avec Django 1.3) :
{% load url from future %}
<p>Lire l'article : <a href="{% url 'entry' entry.url %}">{{entry.title}}</a></p>
Vous noterez l'usage de {% load url from future %}, car le template-tag url a un comportement modifié pour les futures version de Django.
Du côté de la view, cela permet aussi de se simplifier la vie :
def redirect_to_tag(request, section_url):
"""Section now redirect to tag."""
return redirect('tag', permanent=True, tag_url=section_url)
J'ai simplement nommé l'une de mes urls "tag", et la fonction redirect s'occupe du reste. Si je change la forme des url des tags, je n'aurai pas à changer le code de cette view.
Séparer media et static
Apparu avec Django 1.3, la gestion des fichiers "statiques" a été grandement amélioré par l'intégration de django-staticfiles directement dans le projet Django en tant que django.contrib.staticfiles.
J'ai pu découvrir son fonctionnement avec mon dernier projet (un truc secret pour le moment...), et c'est vraiment très pratique. Le principe ? Au lieu d'avoir un répertoire de médias, intégrant les fichiers de l'application (css, js, etc.) et les fichiers téléversés par les utilisateurs, il y a maintenant deux espaces différents.
Je ne vais pas détailler ici tout ce que j'ai eu à faire mais voici un rapide résumé :
- ajout de l'application
django.contrib.staticfiles dans la liste des INSTALLED_APP
- ajout des directives
STATIC_ROOT, STATIC_URL, STATICFILES_DIRS et STATICFILES_FINDERS
- utilisation de
{{STATIC_URL}} dans mes templates à la place de {{MEDIA_URL}}
Ensuite, pour lancer la collecte, la commande suivante fonctionne très bien :
python manage.py collectstatic
Au passage, j'ai aussi simplifié un peu ma configuration Apache, mais ça, c'est un autre sujet.
Et d'autres petites choses...
S'il n'y avait que ça, ce serait trop facile. Et bien, en réalité : il n'y avait que ça.
J'avais déjà fait une première passe pour simplifier grandement le code, faire le ménage, et retirer ce qui n'était pas bien fait et/ou bien pensé (avec un code qui a presque deux ans, c'est normal, j'ai beaucoup appris pendant ce temps). Du coup, une migration assez simple, avec, au déploiement, pas un seul soucis.
J'ajoute, au passage, que c'est une bonne expérience, qui permet de revenir sur ce qui a été fait avant, et sur ce que je fais aujourd'hui - et donc, de pouvoir mesurer l'écart.
J'étais à la DjangoCong 2011, c'était à Marseille, et c'était super. Et ça tombe bien, parce que pour l'édition 2012, j'assiste les organisateurs dans cet évènement, qui a été pris en main par une équipe locale... à Montpellier !
Plus exactement à Carnon-Montpellier, devant une immense étendue de sable chaud et la mer Méditerranée.
Quand ? Le 14 et 15 Avril 2012. Prévoyez vos billets de train !
Où ? À Carnon-Montpellier, dans le Sud de la France. Il y a une gare TGV et tout le confort sur place (la mer, et on l'espère tous du Soleil).
Le lieu ? Dans la journée, ce sera à la Maison Familiale EAGA, et le soir au Gédéon. Oui, ça vend du rêve en barre (j'ai hâte).
Les inscriptions ne sont pas encore ouvertes : elles le seront lorsque l'appel à conférences sera clôturé, c'est à dire aux environs du 13 - 15 Janvier 2012. Donc, si tu as quelque chose à proposer, il est temps de le faire !
Image : La mer devant Carnon-Montpellier
- DjangoCong
- DR
C'était à Rennes, c'était les 17 et 18 Septembre dernier, et j'y étais en tant qu'organisateur local (en gros, cela veut dire aider l'équipe des organisateurs avec mes connaissances du terrain, et les avantages de la proximité).
Dans l'ensemble, ça s'est très bien passé : du monde, des gens contents, de belles rencontres, quelques soucis techniques avec un câble HDMI et une prise capricieuse, des centaines de croissants, des litres de cocas, de cafés et de jus d'orange.
Mais ce n'était pas juste un WE pour moi, puisque j'ai pu participer à son organisation depuis quelques mois déjà. Petit retour d'expérience sur cette édition 2011 de la Pycon Fr.
Avec un peu de retard (c'était il y a une semaine), voici mon petit "compte-rendu" sur la Djangocong, qui se tenait, pour sa seconde édition, à Marseille, les 16 et 17 Avril 2011.
Cette année, donc, j'ai pu y aller, contrairement à l'année dernière, et ce ne sont pas les 6h du Rennes-Marseille (une ligne directe TGV) qui m'en empêchèrent. Même si, à tout prendre, je préfèrerais un lieu plus proche de chez moi pour les prochaines éditions.
La Djangocong, c'est la rencontre d'une communauté, principalement de développeurs francophones, autour du framework python pour le web : Django. Je développe avec ce framework depuis environ 2ans, et il m'apporte tant de satisfaction que j'ai même cherché un travail dans ce domaine - peine perdu, le marché à Rennes est surtout orienté Java.
Mais restons sur la Djangocong :
- Un rassemblement de la communauté Django française.
- Des conférences, des barcamps, des talks, et pleins de mots anglais qui vont bien pour parler de rencontres de gens du même monde
- Quatre organisateurs bénévoles (dont le président et le trésorier de Django-fr)
- Plusieurs sponsors
- L'accent du sud de Marseille
- Un débat pain au chocolat / chocolatine – faux sud / vrai sud
Cependant, il est difficile de résumer la Djangocong en quelques lignes (même cet article ni suffit pas), car la volonté des organisateurs fut de faire de cette rencontre autre chose qu'une suite de conférences techniques. Djangocong, c'est une rencontre entre humains, qui échangent, partagent, discutent, débattent, lancent de belles idées et rentre chez eux avec le sentiment d'appartenir à une communauté.
Image : Djangocong 2011
- Florian Strzelecki
- Creative-Common By-NC
Un billet technique dans lequel j'aborde une solution simple à un problème concret : comment utiliser un captcha avec l'application django-comment fournie de base par le framework Django ?
Je me suis posé cette question lorsque je me suis rendu compte de deux choses :
- le honeypot de django-comment est totalement inutile
- bannir des IPs contre le spam est voué à l'échec
Le mieux était donc d'améliorer la sécurité des formulaires de saisie des commentaires. Oui, mais comment ?
C'est ce que nous allons voir dans la suite de l'article !
Image : Jail with a view on Isola Asinara
- Dirk Hartung (http://www.flickr.com/photos/dirkhartung/)
- Creative Common by-sa
Depuis quelques jours je cherche une application (ou une base pour une application django) permettant de gérer les vignettes de mes images, avec des contraintes de réutilisabilité et surtout, d'intégration dans un environnement déjà existant.
On trouve un peu de tout sur internet, il y a d'ailleurs une liste d'application Django de gestion d'images, que j'ai donc consultée.
J'en ai aussi discuté un peu sur le chan #django-fr d'IRC, pour voir ce que les gens en pensait : manifestement, je ne suis pas le seul à me poser ce genre de questions.
En tout cas, sorl-thumbnail n'est pas ce que je cherche exactement, mais c'est une bonne application, que je souhaite donc vous présenter rapidement.
A force d'entendre parler de gunicorn par Benoit Chesneau (sur Twitter et sur IRC) et divers autres djangonautes français qui passent leur temps sur #django-fr, je me suis dis que je devais m'y mettre sérieusement.
Du coup, hier et avant hier, j'ai pris du temps pour l'installer sur ma machine, configurer mon serveur apache, adapter des petites choses...
En tout cas, ça marche du tonnerre, et mes sites en Django tournent désormais sur du apache en proxy + gunicorn !
Image : Poney
- jacme31 (http://www.flickr.com/photos/jacme31/)
- Creative Common by-sa