| 1 |
======================= |
|---|
| 2 |
Django d'un coup d'oeil |
|---|
| 3 |
======================= |
|---|
| 4 |
|
|---|
| 5 |
Parce que Django a été développé dans une salle de rédaction dont l'environnement |
|---|
| 6 |
change rapidement, il a été conçu pour effectuer les tâches courantes du développement |
|---|
| 7 |
web rapidement et facilement. Vous trouverez ici une introduction informelle sur comment |
|---|
| 8 |
écrire une application web autour d'une base de données avec Django. |
|---|
| 9 |
|
|---|
| 10 |
Le but de ce document est de vous donner suffisamment de détails techniques pour |
|---|
| 11 |
comprendre comment fonctionne Django, mais il n'est en rien un tutoriel ou de référence. |
|---|
| 12 |
Merci de vous référer à la documentation_ Django, bien plus complÚte, quand vous serez prêt |
|---|
| 13 |
à commencer un projet. |
|---|
| 14 |
|
|---|
| 15 |
.. _documentation: ../ |
|---|
| 16 |
|
|---|
| 17 |
Concevez votre modÚle |
|---|
| 18 |
===================== |
|---|
| 19 |
|
|---|
| 20 |
Bien que vous pouviez utiliser Django sans base de données, il contient une couche de |
|---|
| 21 |
correspondance Objet-Relationnel (ORM) dans laquelle vous décrivez la structure de votre |
|---|
| 22 |
base de données en code Python. |
|---|
| 23 |
|
|---|
| 24 |
La syntaxe du modÚle de données permet de représenter vos modÚles de plusieurs façons |
|---|
| 25 |
-- jusqu'ici, il a le mérite de résoudre nos pires problÚmes de schémas de base de |
|---|
| 26 |
données depuis 2 ans. Voici un rapide exemple :: |
|---|
| 27 |
|
|---|
| 28 |
class Reporter(models.Model): |
|---|
| 29 |
full_name = models.CharField(maxlength=70) |
|---|
| 30 |
|
|---|
| 31 |
def __str__(self): |
|---|
| 32 |
return self.full_name |
|---|
| 33 |
|
|---|
| 34 |
class Article(models.Model): |
|---|
| 35 |
pub_date = models.DateTimeField() |
|---|
| 36 |
headline = models.CharField(maxlength=200) |
|---|
| 37 |
article = models.TextField() |
|---|
| 38 |
reporter = models.ForeignKey(Reporter) |
|---|
| 39 |
|
|---|
| 40 |
def __str__(self): |
|---|
| 41 |
return self.headline |
|---|
| 42 |
|
|---|
| 43 |
Installez-le |
|---|
| 44 |
============ |
|---|
| 45 |
|
|---|
| 46 |
Ensuite, lancez l'utilitaire en ligne de commande de Django pour créer automatiquement |
|---|
| 47 |
vos tables dans la base de données :: |
|---|
| 48 |
|
|---|
| 49 |
manage.py syncdb |
|---|
| 50 |
|
|---|
| 51 |
La commande ``syncdb`` examine tous vos modÚles disponibles et crée les |
|---|
| 52 |
tables qui n'existent pas encore dans votre base de données. |
|---|
| 53 |
|
|---|
| 54 |
Appréciez l'API ??? |
|---|
| 55 |
===================== |
|---|
| 56 |
|
|---|
| 57 |
Avec cela, vous avez gratuitement une API Python complÚte pour accéder à vos données. |
|---|
| 58 |
L'API est créée à la volée : aucune génération de code n'est nécessaire :: |
|---|
| 59 |
|
|---|
| 60 |
>>> from mysite.models import Reporter, Article |
|---|
| 61 |
|
|---|
| 62 |
# Aucun reporter n'est encore dans le systÚme. |
|---|
| 63 |
>>> Reporter.objects.all() |
|---|
| 64 |
[] |
|---|
| 65 |
|
|---|
| 66 |
# Créons un nouveau reporter |
|---|
| 67 |
>>> r = Reporter(full_name='John Smith') |
|---|
| 68 |
|
|---|
| 69 |
# Sauvegardons l'objet en base de données. Il faut appeler save() explicitement. |
|---|
| 70 |
>>> r.save() |
|---|
| 71 |
|
|---|
| 72 |
# Il a désormais un ID. |
|---|
| 73 |
>>> r.id |
|---|
| 74 |
1 |
|---|
| 75 |
|
|---|
| 76 |
# Maintenant, le nouveau reporter est dans la base de données. |
|---|
| 77 |
>>> Reporter.objects.all() |
|---|
| 78 |
[John Smith] |
|---|
| 79 |
|
|---|
| 80 |
# Les champs sont représentés comme des attributs d'objets Python. |
|---|
| 81 |
>>> r.full_name |
|---|
| 82 |
'John Smith' |
|---|
| 83 |
|
|---|
| 84 |
# Django fournit une API riche pour la consultation de votre base de données. |
|---|
| 85 |
>>> Reporter.objects.get(id=1) |
|---|
| 86 |
John Smith |
|---|
| 87 |
>>> Reporter.objects.get(full_name__startswith='John') |
|---|
| 88 |
John Smith |
|---|
| 89 |
>>> Reporter.objects.get(full_name__contains='mith') |
|---|
| 90 |
John Smith |
|---|
| 91 |
>>> Reporter.objects.get(id=2) |
|---|
| 92 |
Traceback (most recent call last): |
|---|
| 93 |
... |
|---|
| 94 |
DoesNotExist: Reporter does not exist for {'id__exact': 2} |
|---|
| 95 |
|
|---|
| 96 |
# Créons un article. |
|---|
| 97 |
>>> from datetime import datetime |
|---|
| 98 |
>>> a = Article(pub_date=datetime.now(), headline='Django is cool', |
|---|
| 99 |
... article='Yeah.', reporter=r) |
|---|
| 100 |
>>> a.save() |
|---|
| 101 |
|
|---|
| 102 |
# L'article est désormais en base de données |
|---|
| 103 |
>>> Article.objects.all() |
|---|
| 104 |
[Django is cool] |
|---|
| 105 |
|
|---|
| 106 |
# Les objets Article ont accÚs via l'API aux objets Reporter associés. |
|---|
| 107 |
>>> r = a.reporter |
|---|
| 108 |
>>> r.full_name |
|---|
| 109 |
'John Smith' |
|---|
| 110 |
|
|---|
| 111 |
# Et vice versa : les objets Reporter ont accÚs via l'API aux objets Article. |
|---|
| 112 |
>>> r.article_set.all() |
|---|
| 113 |
[Django is cool] |
|---|
| 114 |
|
|---|
| 115 |
# L'API suit les liens en fonction de vos besoins, effectuant les JOINs |
|---|
| 116 |
# pour vous en arriÚre plan. |
|---|
| 117 |
# Ceci trouve tous les articles d'un reporter dont le nom commence par "John". |
|---|
| 118 |
>>> Article.objects.filter(reporter__full_name__startswith="John") |
|---|
| 119 |
[Django is cool] |
|---|
| 120 |
|
|---|
| 121 |
# Changeons un objet en modifiant un de ses attributs puis appelons save(). |
|---|
| 122 |
>>> r.full_name = 'Billy Goat' |
|---|
| 123 |
>>> r.save() |
|---|
| 124 |
|
|---|
| 125 |
# Effaçons un objet avec delete(). |
|---|
| 126 |
>>> r.delete() |
|---|
| 127 |
|
|---|
| 128 |
Une interface d'administration dynamique, complÚte et configurable -- pas juste un échafaudage (scaffolding) |
|---|
| 129 |
============================================================================================================ |
|---|
| 130 |
|
|---|
| 131 |
Une fois vos modÚles définis, Django peut automatiquement créer une interface |
|---|
| 132 |
d'administration professionnelle et prête à l'emploi -- un site web qui laisse |
|---|
| 133 |
un utilisateur authentifié ajouter, modifier ou supprimer des objets. C'est |
|---|
| 134 |
aussi simple que d'ajouter une ligne de code dans vos classes de modÚles :: |
|---|
| 135 |
|
|---|
| 136 |
class Article(models.Model): |
|---|
| 137 |
pub_date = models.DateTimeField() |
|---|
| 138 |
headline = models.CharField(maxlength=200) |
|---|
| 139 |
article = models.TextField() |
|---|
| 140 |
reporter = models.ForeignKey(Reporter) |
|---|
| 141 |
class Admin: pass |
|---|
| 142 |
|
|---|
| 143 |
La philosophie ici est que votre site est édité par une équipe, ou un client, |
|---|
| 144 |
ou même seulement vous -- et vous ne souhaitez pas vous occuper de concevoir |
|---|
| 145 |
une interface ne servant qu'à gérer le contenu. |
|---|
| 146 |
|
|---|
| 147 |
Une mise en Åuvre typique d'une application Django est de créer des modÚles |
|---|
| 148 |
puis d'avoir une interface d'administration utilisable le plus rapidement |
|---|
| 149 |
possible, afin que votre équipe (ou vos clients) puisse(nt) commencer à entrer des |
|---|
| 150 |
données. Ensuite, développez la façon dont les données seront présentées au public. |
|---|
| 151 |
|
|---|
| 152 |
Concevez vos URLs |
|---|
| 153 |
================= |
|---|
| 154 |
|
|---|
| 155 |
Des URLs propres et élégantes sont d'importants détails dans une application |
|---|
| 156 |
web de haute qualité. Django encourage l'utilisation de belles URL et n'y ajoute |
|---|
| 157 |
pas d'horribles choses dans vos URLs, comme ``.php`` ou ``.asp``. |
|---|
| 158 |
|
|---|
| 159 |
Pour concevoir des URLs pour votre application, vous créez un module Python |
|---|
| 160 |
appelé URLconf. Véritable table des matiÚres de votre application, il contient |
|---|
| 161 |
simplement la correspondance entre le motif de vos URLs et les fonctions |
|---|
| 162 |
callback Python. URLconfs sert également à séparer les URLs du code Python. |
|---|
| 163 |
|
|---|
| 164 |
Voici ce à quoi URLconf peut ressembler pour l'exemple ``Reporter``/``Article`` |
|---|
| 165 |
présenté plus haut :: |
|---|
| 166 |
|
|---|
| 167 |
from django.conf.urls.defaults import * |
|---|
| 168 |
|
|---|
| 169 |
urlpatterns = patterns('', |
|---|
| 170 |
(r'^/articles/(\d{4})/$', 'mysite.views.year_archive'), |
|---|
| 171 |
(r'^/articles/(\d{4})/(\d{2})/$', 'mysite.views.month_archive'), |
|---|
| 172 |
(r'^/articles/(\d{4})/(\d{2})/(\d+)/$', 'mysite.views.article_detail'), |
|---|
| 173 |
) |
|---|
| 174 |
|
|---|
| 175 |
Le code ci-dessus fait correspondre les URLs, de simples expressions réguliÚres, |
|---|
| 176 |
à l'emplacement des fonctions callback Python (les "vues"). Les expressions |
|---|
| 177 |
réguliÚres utilisent des parenthÚses pour "capturer" des valeurs à partir des URLs. |
|---|
| 178 |
Quand un utilisateur demande une page, Django passe chaque motif en revue, dans |
|---|
| 179 |
l'ordre, et s'arrête sur la premiÚre qui correspond à l'URL demandée. (Si aucun |
|---|
| 180 |
motif ne correspond, Django appelle une vue spéciale 404.) C'est extrêmement |
|---|
| 181 |
rapide car les expressions réguliÚres sont compilées au chargement. |
|---|
| 182 |
|
|---|
| 183 |
Une fois qu'un des motifs convient, Django importe et appelle la vue correspondante, |
|---|
| 184 |
qui est une simple fonction Python. Chaque vue se voit passer en paramÚtre un |
|---|
| 185 |
objet request -- qui contient les méta-données de la requête -- et les valeurs |
|---|
| 186 |
capturées par le motif (l'expression réguliÚre). |
|---|
| 187 |
|
|---|
| 188 |
Par exemple, si un utilisateur demande l'URL "/articles/2005/05/39323/", Django |
|---|
| 189 |
va appeler la fonction ``mysite.views.article_detail(request, |
|---|
| 190 |
'2005', '05', '39323')``. |
|---|
| 191 |
|
|---|
| 192 |
Ecrivez vos vues |
|---|
| 193 |
================ |
|---|
| 194 |
|
|---|
| 195 |
Chaque vue s'occupe de faire une de ces deux choses : Retourner un objet |
|---|
| 196 |
``HttpResponse`` contenant le contenu de la page demandée, ou bien lever |
|---|
| 197 |
une exception comme une page ``Http404``. Pour le reste, c'est à vous de |
|---|
| 198 |
jouer. |
|---|
| 199 |
|
|---|
| 200 |
En général, une vue récupÚre des données en fonction des paramÚtres, charge un |
|---|
| 201 |
gabarit (template) et interprÚte le gabarit avec les données récupérées. Voici un exemple |
|---|
| 202 |
pour le ``year_archive`` vu précédemment :: |
|---|
| 203 |
|
|---|
| 204 |
def year_archive(request, year): |
|---|
| 205 |
a_list = Article.objects.filter(pub_date__year=year) |
|---|
| 206 |
return render_to_response('news/year_archive.html', {'year': year, 'article_list': a_list}) |
|---|
| 207 |
|
|---|
| 208 |
Cet exemple utilise le systÚme de gabarits de Django, qui a plusieurs |
|---|
| 209 |
fonctionnalités poussées mais s'efforce de rester simple pour que des |
|---|
| 210 |
non-programmeurs puissent l'utiliser. |
|---|
| 211 |
|
|---|
| 212 |
Concevez vos gabarits |
|---|
| 213 |
====================== |
|---|
| 214 |
|
|---|
| 215 |
Le code ci-dessus charge le gabarit ``news/year_archive.html``. |
|---|
| 216 |
|
|---|
| 217 |
Django recherche les gabarits à un endroit précis, ce qui vous permet de minimiser |
|---|
| 218 |
les redondances parmi les gabarits. Dans vos réglages Django, vous précisez une |
|---|
| 219 |
liste de répertoires à parcourir pour les gabarits. Si un gabarit n'existe pas |
|---|
| 220 |
dans le premier répertoire, il vérifie le suivant, et ainsi de suite. |
|---|
| 221 |
|
|---|
| 222 |
Disons que le gabarit ``news/article_detail.html`` a été trouvé. Voici à quoi |
|---|
| 223 |
il pourrait ressembler :: |
|---|
| 224 |
|
|---|
| 225 |
{% extends "base.html" %} |
|---|
| 226 |
|
|---|
| 227 |
{% block title %}Articles for {{ year }}{% endblock %} |
|---|
| 228 |
|
|---|
| 229 |
{% block content %} |
|---|
| 230 |
<h1>Articles for {{ year }}</h1> |
|---|
| 231 |
|
|---|
| 232 |
{% for article in article_list %} |
|---|
| 233 |
<p>{{ article.headline }}</p> |
|---|
| 234 |
<p>By {{ article.reporter.full_name }}</p> |
|---|
| 235 |
<p>Published {{ article.pub_date|date:"F j, Y" }}</p> |
|---|
| 236 |
{% endfor %} |
|---|
| 237 |
{% endblock %} |
|---|
| 238 |
|
|---|
| 239 |
Les variables sont entourées par des doubles accolades. ``{{ article.headline }}`` |
|---|
| 240 |
signifie "Affiche la valeur de l'attribut headline de l'article". Mais les points |
|---|
| 241 |
ne sont pas seulement utilisés pour consulter un attribut : ils peuvent aussi faire |
|---|
| 242 |
des recherches sur les clés d'un dictionnaire, des recherches sur un index ou des appels de |
|---|
| 243 |
fonction. |
|---|
| 244 |
|
|---|
| 245 |
Notez que ``{{ article.pub_date|date:"F j, Y" }}`` utilise un "tube" Ã la Unix |
|---|
| 246 |
(le caractÚre "|"). C'est ce qu'on appelle un filtre, et c'est un des moyens de |
|---|
| 247 |
filtrer la valeur d'une variable. Dans ce cas, le filtre date formate un objet |
|---|
| 248 |
datetime Python dans le format donné (comme on peut le trouver dans la fonction |
|---|
| 249 |
date de PHP; oui, il y'a une bonne idée dans PHP). |
|---|
| 250 |
|
|---|
| 251 |
Vous pouvez cumuler autant de filtres que vous le souhaitez. Vous pouvez écrire |
|---|
| 252 |
vos propres filtres. Vous pouvez écrire des tags personnalisés, qui exécutent |
|---|
| 253 |
votre code Python en arriÚre plan. |
|---|
| 254 |
|
|---|
| 255 |
Enfin, Django utilise un concept d'héritage de gabarits : c'est ce que fait |
|---|
| 256 |
``{% extends "base.html" %}``. Cela signifie : "Charge d'abord le gabarit |
|---|
| 257 |
appelé 'base', qui définit certains blocs (block), puis remplis-les avec le contenu |
|---|
| 258 |
des blocs suivants". En bref, cela réduit considérablement les redondances dans |
|---|
| 259 |
vos gabarits : chaque gabarit ne définit que ce qui lui est propre (unicité). |
|---|
| 260 |
|
|---|
| 261 |
Voici à quoi pourrait ressembler le gabarit "base.html" :: |
|---|
| 262 |
|
|---|
| 263 |
<html> |
|---|
| 264 |
<head> |
|---|
| 265 |
<title>{% block title %}{% endblock %}</title> |
|---|
| 266 |
</head> |
|---|
| 267 |
<body> |
|---|
| 268 |
<img src="sitelogo.gif" alt="Logo" /> |
|---|
| 269 |
{% block content %}{% endblock %} |
|---|
| 270 |
</body> |
|---|
| 271 |
</html> |
|---|
| 272 |
|
|---|
| 273 |
Pour simplifier, ce gabarit définit le look-and-feel du site (avec le logo), |
|---|
| 274 |
et laisse des "trous" que les gabarits fils rempliront. Cela permet de changer |
|---|
| 275 |
le design juste en modifiant un simple fichier -- le gabarit de base. |
|---|
| 276 |
|
|---|
| 277 |
Il vous permet aussi de créer plusieurs versions du site, avec différents |
|---|
| 278 |
gabarits de base, en réutilisant les gabarits fils. Les créateurs de Django |
|---|
| 279 |
ont utilisés cette technique pour créer de façon étonnante plusieurs versions |
|---|
| 280 |
pour téléphones portables de sites -- simplement en créant un nouveau gabarit |
|---|
| 281 |
de base. |
|---|
| 282 |
|
|---|
| 283 |
Notez que vous n'êtes pas obligé d'utiliser le systÚme de gabarits de Django |
|---|
| 284 |
si vous en préférez un autre. Bien que le systÚme de gabarit soit particuliÚrement |
|---|
| 285 |
bien intégré avec le model en couches de Django, rien ne vous force à l'utiliser. |
|---|
| 286 |
Pour cette raison, vous n'êtes pas non plus obligé d'utiliser l'API de bases |
|---|
| 287 |
de données de Django. Vous pouvez utiliser une autre couche d'abstraction pour |
|---|
| 288 |
votre base de données, vous pouvez lire des fichiers XML, vous pouvez lire des |
|---|
| 289 |
fichiers sur votre disque, ou tout ce que vous voulez. Chaque partie de Django |
|---|
| 290 |
-- modÚles, vues, gabarits -- est indépendante des autres. |
|---|
| 291 |
|
|---|
| 292 |
Ce n'est que la face visible de l'iceberg |
|---|
| 293 |
========================================= |
|---|
| 294 |
|
|---|
| 295 |
Ceci n'était qu'un bref aperçu des fonctionnalités de Django. D'autres |
|---|
| 296 |
fonctionnalités utiles sont: |
|---|
| 297 |
|
|---|
| 298 |
* Un systÚme de cache qui s'intÚgre avec MemCached ou d'autre backends. |
|---|
| 299 |
* Un framework de syndication qui rend la création de flux RSS ou Atom aussi |
|---|
| 300 |
simple a écrire que de petites classes Python. |
|---|
| 301 |
* Des fonctionnalités d'auto-génération de la partie admin encore plus sexy -- |
|---|
| 302 |
cet aperçu n'a qu'éraflé la surface. |
|---|
| 303 |
|
|---|
| 304 |
Les prochaines étapes évidentes sont pour vous de `télécharger Django`, de lire |
|---|
| 305 |
`le tutoriel`_ et de rejoindre `la communauté`_. Merci pour votre intérêt ! |
|---|
| 306 |
|
|---|
| 307 |
.. _télécharger Django: http://www.django-fr.org/telechargement/ |
|---|
| 308 |
.. _le tutoriel: http://www.django-fr.org/documentation/tutorial01/ |
|---|
| 309 |
.. _la communauté: http://www.djangoproject.com/community/ |
|---|