******
Jour 1
******
Introduction à Django
=====================
Django est un framework web écrit en Python, il était au départ développé
pour un environnement de revue de presse électronique appartenant à
**World Online**.
Puis en *Juillet 2005* il a été abstrait et publié comme framework web libre.
Cet héritage est apparent dans l'ensemble du paquetage : dans la
documentation, dans l'interface d'admin, et dans la bibliothèque standard,
par exemple les types de champs gérés (ex: SlugField).
Django inclut tous les composants nécessaires au développement de n'importe
quelle application web de base :
* Correspondance objet-relationnel pour la base de données **(ORM)**.
* Un système de squelette séparant le code Python du code HTML
**(Templates)**.
Django n'utilise pas de serveur d'application tierce partie comme
**CherryPy**. Il fournit par contre un script gestionnaire qui démarre un
serveur de developpement simple. Il s'appuie cependant sur un serveur web
avec la norme **WSGI** ou **FastCGI** pour le déploiement en production.
Ses forces
----------
* Mapping relationel objet, grande API, efficace, remarquée par Guido van Rosum.
* Systeme de cache.
* Backoffice généré.
* Design des URL.
* Système de templates simple, complet et extensible.
* Modules de contributions étendant les fonctionalitées.
* Documentation complète.
* Communautée active.
* Facilité d'apprentissage.
* Découpage intelligent des projets.
* Internationalisation.
* Extensibilitée.
* Rapidité de dévelopement.
* Support de MySQL, PostGres, SQLite...
* Outils d'administration de bases de données.
* Compatibilité WSGI.
* Philosophie DRY.
* Robuste.
Plus d'informations
-------------------
* `DjangoProject
`_
* `Django-fr
`_
Philosophie de code
===================
Vue d'ensemble
--------------
Couplage faible
Les différentes couches du framework ne doivent pas
*se connaître* les unes les autres à moins que cela soit
absolument nécessaire.
Moins de code
Les applications Django doivent utiliser aussi peu de code que
possible; elles doivent rester *agiles*. Django doit permettre de
profiter pleinement des possibilités dynamiques de Python, tel que
l'introspection.
Développement rapide
L'intérêt d'un framework du 21ème siècle est de rendre rapide les
tâches fastidieuses du développement Web. Django doit donc permettre
un développement Web plus rapide.
Ne vous répétez pas *(Don't Repeat Yourself)*
Chaque concept/portion de données distincts doivent résider en un,
et un seul, endroit. *La redondance est mal*. La normalisation est
bien.
Explicite est meilleur qu'implicite
Ceci est un principe au coeur même de Python, qui veut dire que Django
ne doit pas faire de choses trop **magiques**.
La magie ne devrait pas apparaître tant qu'il n'y a pas de raison valable
pour cela. La magie vaut la peine d'être employée seulement si elle
amène un grand confort, inaccessible d'une autre manière, et si
elle n'est pas implémentée de manière à rendre confus les
développeurs qui essayent d'apprendre à utiliser la fonctionnalité.
Cohérence
Le framework devrait être cohérent à tous niveaux. La cohérence
s'applique à tout élément depuis le bas niveau jusqu'au haut niveau.
Modèles
-------
Inclure toute la logique appropriée
Les modèles doivent encapsuler chaque aspect d'un *objet*, selon le
design pattern `Active Record
_` de Martin Fowler.
Les logiques de plus haut niveau doivent aussi être inclues dans les
modèles si possible.
API de la base de données
-------------------------
Efficacité SQL
Elle doit exécuter des requêtes SQL le moins souvent possible, et
optimiser les requêtes en interne.
Syntaxe succinte mais puissante
L'API de base de données doit autoriser de riches et consistantes
requêtes dans un minimum de syntaxe possible. Elle ne doit pas
s'appuyer sur l'import d'autres modules ou d'objets d'aide à la mise
en forme.
Les jointures devraient être réalisées automatiquement, en coulisse,
lorsque nécessaire.
Une option pour exécuter une requête SQL facilement
L'API de base de données doit réaliser qu'elle est un raccourci
mais pas nécessairement un tout-en-un. Le framework doit donc rendre
facile l'écriture de SQL sur mesure -- des requêtes complètes, ou
juste des clauses WHERE personnalisées en tant que paramètres pour
les appels à l'API.
Conception des URLs
-------------------
Couplage faible
Le système d'URL Django doit permettre aux URLs provenant de la
même application d'être différentes dans des contextes
différents. Par exemple, un site peut mettre les articles à
/articles/, alors qu'un autre peut utiliser /nouvelles/.
Flexibilité infinie
Les URLs doivent être aussi flexibles que possible. Toute conception
d'URL imaginable doit être permise.
Encourager les bonnes pratiques
Le framework devrait faire en sorte qu'il soit facile (ou plus
facile) pour un développeur de concevoir de jolies URLs que des
moches. Les extensions de fichier dans les URLs des pages Web devraient
être évités.
URLs permanentes
Techniquement, foo.com/bar et foo.com/bar/ sont deux URLs
différentes, et les robots des moteurs de recherche (et quelques
outils d'analyse du trafic) pourraient les traiter de manière
séparées. Django doit donc faire un effort pour "normaliser" les URLs
afin ne pas permettre la confusion aux robots des moteurs de recherche.
Système de template
-------------------
Séparer la logique de la présentation
Nous voyons un système de template comme un outil contrôlant la
présentation et la logique relative à la présentation -- et c'est
tout. Le système de template ne doit pas supporter de
fonctionnalités qui vont au delà de ces principes de base.
Décourager la redondance
L'héritage au sein des templates, permet de se passer de la duplication
de certains éléments du contenu, tel le footer ou le header.
Etre dissocié du HTML
Le système de template ne doit pas être conçu pour seulement produire du
HTML. Il doit être également bon à générer d'autres formats basés sur du
texte, ou juste du texte.
Sûreté et sécurité
Le système de template, nativement, devrait interdire l'inclusion de
code malicieux -- tel que des commandes supprimant les données en
base.
Extensibilité
Le système de template doit prendre en compte le fait que les auteurs de
templates de niveau avancé peuvent vouloir étendre cette technologie.
C'est le concept derrière les **tags** et les **filtres** de template
sur mesure.
Vues
----
Simplicité
L'écriture d'une vue doit être aussi simple que d'écrire une
fonction Python. Les développeurs ne doivent pas avoir besoin
d'instancier une classe quand une fonction suffit.
Couplage faible
Une vue ne doit pas se soucier du système de template que le
développeur utilise -- ou même si un système de template est utilisé
ou non.
Différencier GET et POST
**GET** et **POST** sont méthodes HTTP distinctss; les développeurs
doivent explicitement utiliser l'un ou l'autre. Le framework doit
facilement distinguer les données GET et POST.
Création d'un projet Django
===========================
Installation de Django
----------------------
Pour commencer à utiliser Django, il est nécessaire de le télécharger et de
l'installer. Nous allons nous baser sur la dernière version stable publiée,
qui est la *1.6*.
Nous allons aussi utiliser **virtualenv** pour cloisonner notre système et
éviter de l'impacter avec les différents modules Python que nous allons
utiliser.
Dans un terminal exécutons ces commandes :
::
$ virtualenv --no-site-packages mon_premier_projet
$ cd mon_premier_projet
$ source ./bin/activate
$ pip install django
Création du projet en local
---------------------------
Maintenant que Django est installé, il est nécessaire de créer un
répertoire *monprojet* qui sera un module Python contenant tout le code de
notre projet.
Dans le répertoire actuel, exécutez la commande suivante ::
$ django-admin.py startproject monprojet
La structure de votre projet est désormais créé.
Qu'est ce qu'un projet Django
------------------------------
Au final qu'est ce qu'un projet Django ?
Si nous regardons le contenu du répertoire de notre projet, nous y
retrouvons plusieurs choses :
``__init__.py``
Ce fichier permet de dire à l'interpreteur Python que ce répertoire
est un module Python. C'est la norme.
``manage.py``
Script Python reprenant les fonctionnalités de django-admin.py et
qui servira aux tâches d'administration de notre projet.
``settings.py``
Ce fichier va contenir toute la configuration de notre projet.
Il sert de point d'entrée à notre projet. Ecrit en python, ce
fichier de configuration est très souple à manipuler.
``urls.py``
Comme son nom l'indique, ce fichier contiendra les urls associées à
notre projet. Il est le squelette du projet, faisant la liaison
entre le code et les urls.
Au final nous pouvons donc dire qu'un projet Django est un module
Python permettant l'administration et le controle des différents
composants intervenant dans le projet. Composants appelés **Applications**.
Création d'une application
==========================
Un projet étant constitué d'applications, Django fournit une commande
pour créer rapidement la structure d'une application au sein de notre
projet, grâce à cette commande :
::
$ python manage.py startapp monapplication
On remarque que nous utilisons désormais le script manage.py, mais
cette action est aussi valable grâce au script *django-admin.py*.
Qu'est ce qu'une application
----------------------------
Une application est aussi un simple module Python. La meilleure preuve est
de regarder le contenu du répertoire *monapplication*. Les fichiers
suivants sont présents :
``__init__.py``
Ceci est le fichier qui prouve que le répertoire est un module
Python, car sa présence l'indique à l'interpréteur.
``models.py``
Fichier Python qui contiendra les classes relatives aux **models**
de notre l'application. Utiliser ce fichier pour écrire ses models est la
norme. Une bonne partie de la logique de notre application se retrouvera
dans ce fichier.
``views.py``
Idem que pour models.py sauf qu'ici seront écrites les vues de
l'application.
``wsgi.py``
Fichier python qui configure le serveur wsgi de l'application
Une application Django est donc un simple module Python définissant un
ensemble de fonctions et de classes, qui seront utlisées au sein de
notre projet.
Standalone versus Coupled applications
--------------------------------------
Il est important de savoir qu'il existe 2 manières de développer une
application :
Coupled
Une application dite **Coupled** est typiquement une application créée par la
commande *startapp* au sein de notre projet. Elle va lier l'application
avec notre projet, ce qui aura l'inconvénient de devoir spécifier
précisement les chemins d'importation de l'application et d'en limiter
grandement la réutilisabilitée.
Dans le cas d'un développement spécifique, ceci ne pose pas de
problèmes, mais il n'est pas recommandé de procéder ainsi.
Standalone
Une application dite **Standalone** est une application indépendante du
projet, qui peut résider n'importe où du moment qu'elle est accessible
par le ``PYTHONPATH``.
Dans le cas d'une application réutilisable et/ou distribuée, il est
nécessaire de procéder ainsi.
Nous utiliserons cette méthode tout au long des travaux pratiques.
Création des modèles
====================
Qu'est ce qu'un model ?
-----------------------
Un model est une classe dans Django servant à intéragir avec une base de
données. Il doit contenir toutes les propriétés et méthodes de notre
objet représenté. Un model pouvant avoir des relations avec d'autres
models, ces relations devront êtres aussi décrites.
Les models serviront de structure à notre application, et en
définiront une bonne partie de la logique.
C'est pour cette raison qu'il est nécessaire de commencer nos
applications par une conception solide de nos models.
Notre première application
--------------------------
Pour se baser sur un exemple concret, nous allons créer une
application de répertoire téléphonique.
Dans votre répertoire de developpement tapez les commandes suivantes :
::
$ mkdir repertoire_telephonique
$ touch repertoire_telephonique/__init__.py
$ touch repertoire_telephonique/models.py
Etant donnée que cette application sera *Standalone* il est nécessaire
qu'elle soit accessible grâce à la variable d'environnement ``PYTHONPATH``.
Pour cela, vous pouvez créer par exemple votre application dans un
répertoire indiqué par ``PYTHONPATH``: ::
$ echo $PYTHON_PATH
Vous pouvez aussi modifier votre variable d'environnement en rajoutant
votre répertoire de développement au ``PYTHONPATH``.
Ou bien créer un lien symbolique depuis un répertoire accessible vers
votre module.
Nos premiers models
-------------------
Nous devons maintenant construire nos models qui vont définir donc la
logique de notre application. Notre application sera constituée de 2
models, l'un représentant un *Contact* et un autre représentant ses
*numéros de téléphones*.
Editons le fichier ``repertoire_telephonique/models.py`` pour qu'il
ressemble à cela :
::
from django.db import models
class Contact(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
def __unicode__(self):
return '%s %s' % (self.first_name, self.last_name)
class Phone(models.Model):
PHONE_CHOICES = (('pro', 'Professionel'),
('mobile', 'Mobile'),
('fixe', 'Fixe'))
contact = models.ForeignKey(Contact, null=True, blank=True)
type = models.CharField(max_length=10, choices=PHONE_CHOICES)
value = models.CharField(max_length=20)
def __unicode__(self):
return '%s %s : %s' % (self.contact, self.type, self.value)
Exercice
--------
Reprendre le model de repertoire_telephonique et lui ajouter la notion d'email
ainsi que de groupe de contact.
Installation des models
-----------------------
Maintenant que nous possédons, nos propres models, il est nécessaire de les
installer pour commencer à les utiliser.
Installer les models d'une application, revient à installer l'application.
Pour cela, il faut éditer les ficher ``settings.py`` de notre projet, et
d'y rajouter le chemin de votre dossier repertoire_telephonique en les
séparant par un "." et non par un "/".
Ex : *'home.monprojet.repertoire_telephonique'*, dans la section ``INSTALLED_APPS``.
Il faut aussi configurer la DATABASE qui est ans le fichier ``settings.py``.
comme ceci : ::
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'chemin de votre dossier monprojet ici avec les "/" # ex : home/documents/django/monprojet'
}
}
Maintenant nous allons établir une synchronisation entre les models et
notre base de donnée. Cette synchronisation servira à créer les tables SQL
décrites par vos models: ::
$ python manage.py syncdb
Ce que nous voyons
------------------
Les models écrits vont servir d'interface avec la base de donnée. Les
attributs de classe définis au sein du model serviront de colonnes et
en définieront le type. Ce sont les Fields.
Il existe des Fields pour à peu prêt chaque cas, il est même possible de
créer ses propres Fields.
Manipulations des models
------------------------
Il possible désormais d'utiliser nos models pour intérargir avec la base de
données :
::
$ python manage.py dbshell
::
>>> from repertoire_telephonique.models import Contact, Phone
>>> Contact.objects.get_or_create(first_name='Julien', last_name='Fantomas')
>>> Contact.objects.all().count()
... 1
Introduction aux URLs
=====================
Le système d'URLs au sein de Django est une des fonctionnalités les plus
intéressantes de Django pour ces raisons suivantes :
Motif
Les URLs sont constituées de motifs permettants la variation et
l'écriture de n'importe qu'elle URL et le passage de paramètres de
manière élégante.
Rapidité
Les URLs sont compilées une seule fois, au démarrage du serveur pour un
gain de temps.
Couplage faible
Les URLs sont décentralisées, et permettent l'association entre le motif
de l'URL et une vue.
Il est bon de savoir que les URLs peuvent être nommées, pour un soucis
de claireté et aussi pour eviter d'avoir un couplage fort au sein de
vos templates et vues. Nous verrons cela en détail plus tard.
Exemples
--------
Voici un exemple simple de vue en liste et detaillée :
::
urlpatterns = patterns('django.views.generic.list_detail',
url(r'^$', 'object_list',
name='my_object_list'),
url(r'^(?P\d+)/$', 'object_detail',
name='my_object_detail'),
)
Ce qui donnera à l'utilisation dans votre navigateur les URLs suivantes :
* http://example.com/
* http://example.com/42/
Activation de l'administration
==============================
Une autre des fonctionnalités les plus utiles au sein de Django, et qui a
permis au framework de se diffuser rapidement, est sans conteste
`l'application d'administration
`_.
L'application d'administration est un module Python fournis de base
dans la distrbution de Django, se situant dans le répertoire
**contrib** de notre module Django. Nous pouvons voir que dans ce
dossier d'autres applications sont fournies avec les sources de Django.
Administration simple
---------------------
Une des premières choses à effectuer est d'installer le module
d'administration.
Pour cela dans le fichier ``settings.py`` de notre projet ajoutons
**'django.contrib.admin'** à l'intérieur de la section ``INSTALLED_APPS``.
Pour continuer l'installation il est nécessaire d'associer une URL aux vues
du module d'administration.
Le fichier ``urls.py`` situé dans notre projet contient déjà un exemple
d'URLs pour accèder aux vues de l'administration, mais il est commenté.
Décommentons les lignes suivantes, pour avoir ceci :
::
from django.contrib import admin
admin.autodiscover()
url(r'^admin/', include(admin.site.urls)),
Ensuite exécutons la commande suivante, pour synchroniser les models
contenus dans l'application *admin* afin d'en assurer son fonctionnement.
::
$ python manage.py syncdb
Désormais, si on lance le serveur de développement de Django, par la
présente commande,
::
$ python manage.py runserver
on peut accéder à l'interface d'administration grâce à cette url :
http://localhost:8000/admin
Une fois identifié vous pouvez voir une liste des différentes
applications installées sur le serveur et qui sont administrables.
Par contre, nous ne voyons pas notre application au sein de
l'administration, ce qui est plutot dommage, donc nous allons remédier à
cela.
Administration de nos application
---------------------------------
Pour activer nos applications aux seins du module d'administration c'est
très simple, il suffit simplement d'enregistrer nos models dans le site
d'administration.
Pour cela nous allons créer un module ``admin.py`` au sein de notre
application de répertoire téléphonique.
::
$ cd repertoire_telephonique/
$ touch admin.py
Maintenant editons le pour qu'il ressemble à cela :
::
from django.contrib import admin
from repertoire_telephonique.models import Contact
from repertoire_telephonique.models import Phone
admin.site.register(Phone)
admin.site.register(Contact)
Désormais si on relance le serveur de développement, et que l'on recharge
la page d'accueil de l'administration, nous y voyons apparaitre notre
application avec ses tables prêtes à être administrées.
Le résultat est plutôt basique, mais il est possible d'aller plus loin dans
la configuration de l'administration de nos models.
Administration évoluée
----------------------
Pour atteindre un résultat où les vues d'administration sont efficaces
et facile à utiliser, il est souvent nécessaire de les configurer.
Il nous faut donc créer différentes classes définissants le comportenant de
chacuns de nos models dans l'administration.
Ajoutons ce bout de code dans notre fichier ``admin.py`` :
::
class ContactAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name')
class PhoneAdmin(admin.ModelAdmin):
list_display = ('contact', 'type', 'value')
admin.site.register(Phone, PhoneAdmin)
admin.site.register(Contact, ContactAdmin)
Nous venons juste modifier l'affichage de la vue en liste de l'admin, mais
elle paraît déjà plus utile.
Désormais si on regarde la `documentation du module d'administration
`_ nous
voyons qu'il existe pas mal de possibilités pour personaliser l'interface
d'administration.
Essayons un peu.
Exercice
--------
Rajouter dans l'admin les emails et groupe de contact.
Sur la vue des Phones, rajouter un filtre sur le type.