Approfondissements
Générer d’autres formats que du HTML
1. Générer un fichier PDF
Dans le chapitre Les templates concernant les templates on a vu que l’on peut générer n’importe quel format basé sur du texte avec les templates Django. Ce qui veut dire que l’on peut générer du XML et donc par exemple des fichiers ODT (OpenDocument de LibreOffice/OpenOffice), avec un peu d’effort tout de même. Pour ce qui est du format PDF, il existe de nombreux outils que l’on peut utiliser pour en générer à partir d’une page HTML/CSS, de XML ou même de ODT. Citons :
xhtml2pdf : convertisseur HTML/CSS vers PDF écrit en Python. Intégrable simplement et immédiatement à Django.
« The Apache™ FOP Project » : générateur de fichiers PDF à partir de commandes en XML. Convertisseur écrit en Java, accessible en ligne de commande.
django-uwkhtmltopdf : convertisseur HTML vers PDF basé sur uwkhtmltopdf.
django-webodt : convertisseur HTML et ODT vers PDF, Images, .doc (Word) ou RTF.
weasyprint : convertisseur HTML vers PDF.
HTMLdoc : script de conversion du HTML vers le PDF.
Tous ces outils restent de la conversion de formats texte vers HTML et donc utilisent des templates. Ce n’est donc pas ce que nous allons voir dans ce chapitre. Comment construire un fichier sans passer par des templates ? Ce principe s’applique à tous les formats binaires ou spéciaux. Nous verrons deux exemples : générer un PDF et générer un fichier CSV avec la librairie CSV de Python. Le but est de voir que l’on peut utiliser toutes les librairies et outils Python...
Personnaliser le modèle « USER MODEL » de Django
Le modèle de gestion des utilisateurs utilisé par Django et que l’on trouve dans django.contrib.auth est très pratique puisque l’on peut immédiatement construire un site gérant tous les aspects de base de l’enregistrement et du contrôle des utilisateurs, login, sessions, droits d’accès, etc. Seulement il va arriver un moment où l’on souhaite pouvoir personnaliser ce modèle pour lui ajouter de nouveaux comportements, de nouveaux champs ou même une logique particulière. C’est bien sûr faisable et peut être réalisé de plusieurs façons en fonction du but recherché.
Si l’on souhaite simplement enrichir le modèle User existant, car on en est globalement satisfait et que l’on n’a pas besoin de rajouter des champs, il suffit d’utiliser un modèle proxy, pour cela reportez-vous au chapitre L’ORM et les modèles Django à la section concernant l’héritage, il n’y a aucune difficulté à réaliser cela.
Si l’on souhaite simplement ajouter des champs mais sans créer son propre modèle de gestion des utilisateurs, le plus simple est de relier une « extension », qui est un modèle Django contenant les champs et le comportement spécifiques au modèle User existant par une relation un vers un.
Enfin, si on souhaite aller plus loin dans la modification du modèle de gestion des utilisateurs, il faudra créer un modèle spécifique respectant certaines règles et contraintes et l’installer dans Django.
Une réelle difficulté pour personnaliser le modèle User va apparaitre dès que l’on va vouloir étendre le modèle User de Django et, en même temps, utiliser une ou plusieurs applications tierces ; applications qui ont elles-mêmes personnalisé le modèle User. Vous risquez de devoir soit renoncer à utiliser une application, soit accepter d’avoir des champs en doublon, soit réécrire entièrement un modèle réalisant la synthèse entre les différents modèles User. Bref, cela peut s’avérer assez problématique. Cela...
Les signaux
Django propose un mécanisme très utile qui est un gestionnaire de signaux. Les signaux sont émis par un émetteur à destination de récepteurs qui se sont enregistrés sur le signal. Le récepteur est une fonction Python. Cela permet d’être informé lorsque certaines opérations sont réalisées quelque part dans le framework.
Vous pouvez créer vos propres signaux pour votre application et Django contient un ensemble de signaux pour les actions courantes du framework. En voici les principaux :
Les signaux relatifs aux modifications des instances de modèles :
django.db.models.signals.pre_save et django.db.models.signals.post_save
Qui sont des signaux respectivement activés avant et après l’appel à la méthode save().
django.db.models.signals.pre_delete et django.db.models.signals.post_delete
Qui sont des signaux respectivement activés avant et après l’appel à la méthode delete() d’une instance ou d’un QuerySet.
django.db.models.signals.pre_init et django.db.models.signals.post_init
Qui sont des signaux respectivement activés avant et après la création d’une instance.
django.db.models.signals.m2m_changed
Qui est activé lorsqu’un champ ManyToManyField est modifié.
Les signaux relatifs aux requêtes :
django.core.signals.request_started et django.core.signals.request_finished
Qui sont activés avant que Django débute ou termine une requête HTTP.
django.core.signals.got_request_exception
Qui est activé par une exception...
La sécurité
1. Protection contre le clickjacking
Le clickjacking, ou détournement de clic, est une technique malveillante visant à pousser un internaute à fournir des informations confidentielles ou à prendre le contrôle de son ordinateur en l’incitant à cliquer sur des pages apparemment sûres. Le terme de clickjacking a été inventé par Robert Hansen et Jeremiah Grossman (Wikipedia).
Un exemple d’utilisation du clickjacking (http://ratmort.com/blog/adsense-clickjacking)
Un utilisateur arrive sur un site qui semble inoffensif et qui récapitule tous les concerts programmés dans les prochains mois. Celui-ci lui propose de sélectionner une ville dans une liste et de cliquer sur un bouton "Valider" afin de lui présenter une liste de concerts disponibles dans sa région. En réalité, une page Facebook est cachée en transparence. C’est sur cette page que le visiteur clique, sans la voir. Les deux clics qu’il pense effectuer sur le site de concerts correspondent en fait exactement aux emplacements, sur la page de Facebook, qui rend son profil visible à tous, ou encore envoie une invitation à tous ses contacts.
Protéger son site contre le clickjacking
Les navigateurs modernes permettent d’activer une protection contre le clickjacking grâce à l’option X-Frame-Options dans le header HTTP. Cette option indique si la page autorise ou non le navigateur à l’afficher dans une frame ou une iframe. Si X-Frame-Options et positionné à DENY, alors le navigateur refusera de charger la page dans une frame, quelle que soit la façon dont la requête est effectuée. Malheureusement tous les navigateurs ne supportent pas cette option. Voici la liste de ceux qui la supportent : Internet Explorer à partir de la version 8, Firefox à partir de la version 3.6.9, Opera à partir de la version 10.5, Safari à partir de la version 4 et Chrome à partir de la version 4.1.
Django permet de gérer simplement cette option du header, avec un middleware qui modifie le header en positionnant l’option et des décorateurs qui permettent de préciser sur une base vue par vue si on accepte ou non que la vue soit affichée sous forme de frame ou d’iframe.
Utilisation :
Pour...
La création de commandes en mode console
manage.py permet d’exécuter un certain nombre de commandes, runserver, shell, syncdb, migrate, etc. Les développeurs Django ont la possibilité d’enrichir la liste des commandes disponibles en ajoutant les commandes de leur application.
À quoi cela sert-il ? Un site peut avoir à exécuter périodiquement certaines opérations de vérification ou de nettoyage, pouvoir les lancer sous la forme d’une commande (d’un script) ou pouvoir les automatiser en les installant dans la crontab d’UNIX ou son équivalent Windows (tâches programmées).
Pour cela il faut créer un répertoire management/commands à votre application. Django enregistrera automatiquement les commandes définies, c’est-à-dire les modules de ce répertoire qui ne commencent pas par le caractère « _ » (underscore). Vous devez donc respecter la structure suivante de fichiers pour votre projet :
mon_application/
__init__.py
admin.py
models.py
management/
__init__.py
commands/
__init__.py
_ne_pas_charger.py
archiver.py
views.py
Dans cet exemple, la commande « archiver »...
Les exceptions
En plus des exceptions Python traditionnelles, Django possède ses propres exceptions réparties en quatre catégories : celles du noyau Django (core), celles relatives aux URL, celles relatives aux bases de données et celles relatives à HTTP.
1. Exceptions de base du noyau Django
Elles sont définies dans django.core.exceptions, et sont les suivantes :
DoesNotExist
Cette exception est levée lorsqu’une requête comme get(), devant retourner un seul objet, échoue et n’en retourne aucun.
ObjectDoesNotExist
dont la classe de base est DoesNotExist.
MultipleObjectsReturned
Cette exception est levée lorsqu’une requête comme get(), devant retourner un seul objet, échoue en retournant plusieurs objets.
SuspiciousOperation
Cette exception est levée lorsque Django considère cette opération comme douteuse, par exemple lors de l’altération d’un cookie de session. Elle possède plusieurs sous-classes, permettant de préciser la nature de l’opération douteuse.
PermissionDenied
Cette exception est levée lorsque l’utilisateur n’a pas les droits correspondants pour réaliser une opération.
ViewDoesNotExist
La vue demandée n’existe pas (écrivez-la).
MiddlewareNotUsed
Cette exception est levée lorsqu’un middleware précise qu’il n’est pas utilisé....