Apprenons par l’exemple.
Au long de ce tutoriel, nous allons vous amener à la création d’une application de sondage simple.
Elle se composera de deux parties :
Nous supposerons que Django est déjà installé (en). Vous pouvez savoir si Django est installé en démarrant le shell Python et en entrant import django. Si cette commande s’exécute sans erreur, Django est installé.
Où obtenir de l’aide :
Si vous avez des problèmes au long de ce tutoriel, postez un message sur django-users (en) ou passez sur #django-fr sur irc.freenode.net pour discuter avec d’autres utilisateurs de Django qui pourraient vous aider.
Si c’est la première fois que vous utilisez Django, vous devrez vous occuper de quelques éléments de configuration initiaux. Plus précisément, vous devrez lancer la génération automatique de code qui mettra en place un projet Django – un ensemble de règlages particuliers à une instance de Django, qui comprendra la configuration de la base de données, des options spécifiques à Django et d’autres propres à l’application.
Depuis un terminal en ligne de commande, cd dans un répertoire dans lequel vous souhaitez conserver votre code, puis lancez la commande django-admin.py startproject mysite. Cela va créer un répertoire mysite dans le répertoire courant.
Note
Vous devez éviter de nommer vos projets en utilisant des noms réservés de Python ou des noms de composants de Django. Cela signifie en particulier que vous devez éviter d’utiliser le nom django (qui entrerait en conflit avec Django lui-même) ou test (qui entrerait en conflit avec un composant intégré de Django).
django-admin.py (en) doit se trouver sur le chemin de recherche de votre système si vous avez installé Django en utilisant python setup.py. S’il n’est pas sur ce chemin, vous le trouverez dans site-packages/django/bin, où `site-packages` est un répertoire de votre installation Python. Dans ce cas vous devriez envisager de faire un lien symbolique de django-admin.py (en) vers un répertoire de votre chemin de recherche système, comme /usr/local/bin.
Où devrait se trouver ce code ?
Si vous avez une expérience en PHP, vous avez probablement l’habitude de placer votre code dans le répertoire racine de votre serveur Web (comme /var/www/). Avec Django, ne le faites pas. Ce n’est pas une bonne idée de mettre du code Python dans le répertoire racine de votre serveur Web, parce que cela crée le risque que l’on puisse voir votre code sur le Web, ce qui n’est pas bon pour la sécurité.
Mettez votre code dans un répertoire en dehors de la racine de votre serveur Web, comme par exemple home/mycode.
Voyons ce que startproject a créé :
mysite/
__init__.py
manage.py
settings.py
urls.py
Ces fichiers sont :
Vérifions que tout fonctionne comme prévu. Déplacez-vous dans le répertoire mysite si ce n'est pas déjà fait, et lancez la commande python manage.py runserver. Vous verrez les messages suivants défiler :
Validating models...
0 errors found.
Django version 1.1, using settings 'mysite.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Vous avez démarré le serveur de développement de Django, un serveur Web léger entièrement écrit en Python. Nous l'avons inclus avec Django de façon à vous permettre de développer rapidement, sans avoir à vous occuper de la configuration d'un serveur de production -- comme Apache -- tant que vous n'en avez pas besoin.
C'est le moment de noter soigneusement ceci : N'UTILISEZ JAMAIS ce serveur pour quoi que ce soit qui s'approche d'un environnement de production. Il est fait seulement pour tester votre travail pendant le développement (notre métier est le développement de frameworks Web, pas de serveurs Web.)
Maintenant que le serveur tourne, allez à l'adresse http://127.0.0.1:8000 avec votre navigateur Web. Vous verrez une page avec le message "Welcome to Django" sur un joli fond bleu pastel. Ça marche !
Changer le port
Par défaut, la commande runserver démarre le serveur de développement sur le port 8000.
Si vous voulez changer cette valeur, passez-là comme argument sur la ligne de commande. Par exemple, cette commande démarre le serveur sur le port 8080 :
python manage.py runserver 8080
Si vous voulez changer l'IP du serveur, passez-là comme argument avec le port. Pour écouter toutes les IP publiques (utile si vous souhaitez montrer votre travail à des personnes sur d'autres ordinateurs), faites :
python manage.py runserver 0.0.0.0:8000
La documentation complète du serveur de développement est dans la référence de runserver.
Maintenant, éditez settings.py. C'est un module Python tout à fait normal, avec des variables de module qui représentent des règlages de Django. Changez ces règlages pour indiquer les paramètres de connexion de votre base de données :
DATABASE_ENGINE -- 'postgresql_psycopg2', 'mysql' ou 'sqlite3'. D'autres backends sont également disponibles.
DATABASE_NAME -- Le nom de votre base de données. Si vous utilisez SQLite, la base de données sera un fichier sur votre ordinateur : dans ce cas, DATABASE_NAME doit être le chemin absolu complet, y compris le nom de fichier, de celui-ci. Si ce fichier n'existe pas, il sera créé automatiquement lorsque vous synchroniserez la base de donnée (voir ci-dessous).
Lorsque vous spécifiez le chemin, utilisez toujours des barres de fraction classiques, même sous Windows (par exemple C:/homes/user/mysite/sqlite3.db).
DATABASE_USER -- Le nom d'utilisateur pour votre base de données (inutile pour SQLite).
DATABASE_PASSWORD -- Le mot de passe pour votre base de données (inutile pour SQLite).
DATABASE_HOST -- L'hôte sur lequel se trouve votre base de données. Laissez une chaîne de caractères vide si votre serveur de base de données est sur la même machine physique (inutile pour SQLite).
Si vous débutez avec les bases de données, nous vous recommandons d'utiliser simplement SQLite (en renseignant DATABASE_ENGINE avec 'sqlite3'). SQLite est inclus dans Python à partir de la version 2.5, donc vous n'aurez rien d'autre à installer.
Note
Si vous utilisez PostgreSQL ou MySQL, assurez-vous maintenant d'avoir créé la base de données. Faites-le avec "CREATE DATABASE nom_de_la_base;" dans le shell de votre base de données.
Si vous utilisez SQLite, vous n'avez rien à créer à l'avance - le fichier de la base de données sera automatiquement créé lorsque ce sera nécessaire.
En éditant settings.py, notez le règlage INSTALLED_APPS vers la fin du fichier. Cette variable contient le nom des applications Django qui sont actives dans cette instance de Django. Les applications peuvent être utilisées dans des projets différents, et vous pouvez empaqueter et distribuer les vôtres pour que d'autres les utilisent dans leurs projets.
Par défaut, INSTALLED_APPS contient les applications suivantes, qui sont toutes contenues dans Django :
Ces applications sont incluses par défaut parce qu'elles sont celles qui sont le plus communément utilisées.
Chacune de ces applications utilise toutefois au moins une table de la base de données, donc il nous faut créer les tables dans la base avant de pouvoir les utiliser. Pour ce faire, lancez la commande suivante :
python manage.py syncdb
La commande syncdb va créer toutes les tables de base de données nécessaires aux applications listées dans le règlage INSTALLED_APPS de votre fichier settings.py. Vous verrez un message pour chaque table créée, et il vous sera proposé de créer un compte de super-utilisateur pour le système d'authentification. Faites-le.
Si vous les souhaitez, lancez le client de ligne de commande de votre base de données, et tapez \dt (PostgreSQL), SHOW TABLES; (MySQL), ou .schema (SQLite) pour afficher les tables que Django a créées.
Pour les minimalistes
Comme il a été indiqué ci-dessus, les applications incluses par défaut sont les plus communes, mais tout le monde n'en a pas forcément besoin. Si vous n'avez pas besoin d'une d'entre elles (ou de toutes), vous êtes libres de commenter ou effacer les lignes concernées du règlage INSTALLED_APPS avant de lancer syncdb. La commande syncdb ne créera que les tables nécessaires aux applications listées dans INSTALLED_APPS.
Maintenant que votre environnement -- un "projet" -- est en place, vous êtes prêt à commencer à travailler.
Chaque application que vous écrivez dans Django est en fait un package Python, quelquepart sur votre chemin de recherche Python (en), qui respecte certaines conventions. Django est livré avec un utilitaire qui génère automatiquement la structure de répertoire de base d'une application, ce qui vous permet de vous concentrer sur l'écriture du code, plutôt que sur la création de répertoires.
Projets et applications
Quelle est la différence entre un projet et une application ? Une application est une application Web qui fait quelquechose -- par exemple un système de blog, une base de données publiques ou une application de sondage. Un projet est un ensemble de règlages et d'applications pour un site Web particulier. Un projet peut contenir plusieurs applications. Une application peut apparaître dans plusieurs projets.
Dans ce tutoriel, nous allons créer notre application de sondage dans le répertoire mysite, par souci de simplicité. En conséquence, l'application sera liée au projet -- c'est à dire, le code Python dans l'application de sondage sera référencé par mysite.polls. Plus loin dans ce tutoriel, nous discuterons du découplage entre projet et application.
Pour créer votre application, assurez-vous d'être dans le répertoire mysite et entrez cette commande :
python manage.py startapp polls
Cela va créer un répertoire polls, qui se présente de la façon suivante :
polls/
__init__.py
models.py
views.py
Cette structure de répertoire accueillera l'application de sondage.
La première étape dans l'écriture d'une application Web utilisant une base de données dans Django est la définition de vos modèles -- essentiellement, votre schéma de base de données, avec quelques métadonnées supplémentaires.
Philosophie
Un modèle est la source d'information unique et définitive pour vos données. Il contient les champs essentiels et le comportement attendu des données que vous stockerez. Django utilise la philosophie DRY (en), ce qui signifie Don't Repeat Yourself, ne vous répétez pas. Le but est de définir le modèle de vos données à un seul endroit, et ensuite de dériver automatiquement ce qui est nécessaire à partir de celui-ci.
Dans notre application de sondage simple, nous allons créer deux modèles : un pour les sondages (polls) et un pour les possibilités de choix (choices). Un sondage possède une question et une date de mise en ligne. Une possibilité de choix a deux champs : le texte représentant le choix, et le décompte des votes. Chaque choix est associé à un sondage.
Ces concepts sont représentés par de simples classes Python. Éditez le fichier polls/models.py de façon à ce qu'il ressemble à ceci :
from django.db import models
class Poll(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice = models.CharField(max_length=200)
votes = models.IntegerField()
Erreurs au sujet de max_length
Si Django vous envoie un message d'erreur indiquant : max_length is not a valid argument, vous utilisez probablement une ancienne version de Django (cette version du tutoriel est écrite pour la dernière version de développement de Django). Si vous utilisez une version de Django issue du dépôt Subversion (voir la documentation de l'installation - en - pour plus de détails), vous ne devriez pas avoir de problèmes.
Si vous voulez rester avec une version plus ancienne de Django, allez lire le tutoriel de Django 0.96 (en), parce que celui que vous lisez maintenant couvre plusieurs fonctionnalités qui n'existent que dans la version de développement de Django.
Le code est trivial. Chaque modèle est représenté par une classe qui hérite de Model. Chaque modèle possède des variables de classe, chacune d'entre elles représentant un champ de la base de données pour ce modèle.
Chaque champ est représenté par une instance d'une classe Field -- par exemple, CharField pour les champs de type caractère, et DateTimeField pour les champs date et heure. Cela indique à Django quel type de données contient chaque champ.
Le nom de chaque instance de Field (par exemple, question ou pub_date) est le nom du champ en interne. Vous l'utiliserez dans votre code Python, et votre base de données l'utilisera comme nom de colonne.
Vous pouvez utilisez le premier argument de position (facultatif) d'un Field pour donner un nom plus lisible au champ. C'est utilisé par le système d'introspection de Django, et aussi pour la documentation. Si cet argument est absent, Django utilisera le nom du champ en interne. Dans l'exemple, nous n'avons défini qu'un seul nom plus lisible, pour Poll.pub_date. Pour tous les autres champs, nous avons considéré que le nom interne était suffisament lisible.
Certaines classes Field ont des attributs obligatoires. La classe CharField, par exemple, a besoin d'un attribut max_length. Ce n'est pas seulement utilisé dans le schéma de base de données, mais également pour valider les champs, comme nous allons voir prochainement.
Finalement, notez que nous définissons une relation, en utilisant ForeignKey. Cela indique à Django que chaque vote (Choice) n'est relié qu'à un seul sondage (Poll). Django propose tous les modèles classiques de relations : plusieurs-à-un, plusieurs-à-plusieurs, un-à-un.
Ce petit morceau de code décrivant les modèles fournit beaucoup d'information à Django. Avec, il est capable de :
Mais il faut d'abord indiquer à notre projet que l'application de sondages polls est installée.
Philosophie
Les applications de Django sont comme des pièces d'un jeu de construction : vous pouvez utiliser une application dans plusieurs projets, et vous pouvez distribuer les applications, parce qu'elles n'ont pas besoin d'être liées à une installation Django particulière.
Éditez encore une fois le fichier settings.py, et modifiez le réglage INSTALLED_APPS pour qu'il contienne la chaîne de caractéres 'mysite.polls'. Il devrait donc ressembler à ceci :
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'mysite.polls'
)
Maintenant, Django sait que mysite doit inclure l'application polls. Exécutons une autre commande :
python manage.py sql polls
Vous devriez voir quelquechose de similaire à ceci (les instructions SQL CREATE TABLE pour l'application de sondage) :
BEGIN;
CREATE TABLE "polls_poll" (
"id" serial NOT NULL PRIMARY KEY,
"question" varchar(200) NOT NULL,
"pub_date" timestamp with time zone NOT NULL
);
CREATE TABLE "polls_choice" (
"id" serial NOT NULL PRIMARY KEY,
"poll_id" integer NOT NULL REFERENCES "polls_poll" ("id"),
"choice" varchar(200) NOT NULL,
"votes" integer NOT NULL
);
COMMIT;
Notez les points suivants :
Si cela vous intéresse, vous pouvez aussi utiliser les commandes suivantes :
L'examen de ce qu'affichent ces commandes peut vous aider à comprendre ce qui se passe en coulisses.
Maintenant, exécutez la commande syncdb pour créer les modèles dans votre base de données :
python manage.py syncdb
La commande syncdb exécute les instructions sql de 'sqlall' dans votre base de données, pour toutes les applications de INSTALLED_APPS qui n'existent pas encore dans celle-ci. Cela crée toutes les tables, les données initiales et les index pour toutes les applications que vous avez ajoutées à votre projet depuis la dernière fois que vous avez fait un 'syncdb'. syncdb peut être appellée aussi souvent que vous le souhaitez, et ne fera que créer les tables qui n'existent pas encore.
Lisez la documentation de django-admin.py (en) pour avoir toutes les informations sur ce que manage.py peut faire.
Maintenant, utilisons un shell interactif Python pour jouer avec l'API que Django met à votre disposition. Pour lancer un shell Python, utilisez cette commande :
python manage.py shell
Nous utilisons celle-ci au lieu de simplement taper "python", parce que manage.py met en place l'environnement du projet pour vous. "Mettre en place l'environnement" signifie deux choses :
Mettre mysite dans sys.path. Pour des raisons de souplesse, plusieurs parties de Django se réfèrent aux projets dans la notation classique de Python, en utilisant des points comme séparateurs dans les chemins (par exemple, 'mysite.polls.models'). Pour que cela fonctionne, le package mysite doit être dans le sys.path.
On a déjà vu un exemple de ceci : le réglage INSTALLED_APPS est une liste de packages dans cette notation avec les points.
Renseigner la variable d'environnement DJANGO_SETTINGS_MODULE. Elle indique à Django le chemin de votre fichier settings.py.
Se passer de manage.py
Si vous préférez ne pas utiliser manage.py, pas de problème. Assurez-vous simplement que mysite est au niveau racine dans votre chemin de recherche Python (c'est-à-dire que import mysite fonctionne) et renseignez vous-même la variable d'environnement DJANGO_SETTINGS_MODULE à mysite.settings.
Pour plus d'information sur tout ceci, voyez la documentation de django-admin.py (en).
Une fois dans le shell, explorez l'API de base de données (en) :
>>> from mysite.polls.models import Poll, Choice # Importation des classes de modèles que nous venons d'écrire.
# Il n'existe pas encore de sondage.
>>> Poll.objects.all()
[]
# Création d'un nouveau sondage.
>>> import datetime
>>> p = Poll(question="Quoi de neuf ?", pub_date=datetime.datetime.now())
# Sauvegarde de l'objet dans la base de donnéees. Vous devez appeler save()
explicitement.
>>> p.save()
# Maintenant, l'objet a une ID. Notez que le retour peut être "1L" au lieu
# de 1, suivant la base de données que vous utilisez. Ce n'est rien, cela
# signifie simplement que votre moteur de base de données renvoie les
# entiers à Python sous la forme d'entiers longs.
>>> p.id
1
# Accèdez aux colonnes de la base de données par des attributs Python.
>>> p.question
"Quoi de neuf ?"
>>> p.pub_date
datetime.datetime(2007, 7, 15, 12, 00, 53)
# Modifiez les valeurs en changeant les attributs, puis en appelant save().
>>> p.pub_date = datetime.datetime(2007, 4, 1, 0, 0)
>>> p.save()
# objects.all() affiche tous les sondages de la base de données.
>>> Poll.objects.all()
[<Poll: Poll object>]
Une seconde. <Poll: Poll object> n'est, à l'évidence, pas une représentation de cet objet très utile. On va arranger cela en éditant le modèle des sondages (dans le fichier polls/models.py) et en ajoutant une méthode __unicode__() à Poll et à Choice :
class Poll(models.Model):
# ...
def __unicode__(self):
return self.question
class Choice(models.Model):
# ...
def __unicode__(self):
return self.choice
Si __unicode__() ne semble pas fonctionner
Si vous ajoutez la méthode __unicode__() à votre modèle et que vous ne voyez pas de changement dans sa représentation, il est très probable que vous utilisiez une ancienne version de Django. Cette version du tutoriel est écrite pour la dernière version de développement de Django. Si vous utilisez une version de développement issue du dépôt Subversion (voir, la documentation de l'installation (en) pour plus d'information), vous ne devriez pas avoir de problème.
Si vous voulez rester avec cette ancienne version de Django, passez au tutoriel de Django 0.96 (en), parce que celui que vous lisez actuellement couvre plusieurs fonctionnalités qui n'existent que dans la version de développement de Django.
Il est important d'ajouter des méthodes __unicode__() à vos modèles, non seulement parce que c'est plus pratique lorsque vous utilisez le shell interactif, mais aussi parce que la représentation des objets est très utilisée dans l'interface d'administration automatique de Django.
Pourquoi __unicode__() et pas __str__()?
Si vous êtes familier de Python, vous avez peut être l'habitude d'ajouter des méthodes __str__() à vos classes, plutôt que __unicode__(). Nous utilisons cette dernière parce que les modèles de Django utilisent Unicode par défaut. Toute l'information stockée dans votre base de données est convertie en Unicode avant de vous être retournée.
Les modèles Django ont une méthode __str__() par défaut, qui appelle __unicode__() et convertit le résultat en bytestring UTF-8. Cela signifie que unicode(p) renverra une chaîne Unicode, et str(p) renverra une chaîne normale, avec les caractères encodés en UTF-8.
Si vous ne comprenez rien à tout ça, rappellez-vous simplement d'ajouter une méthode __unicode__() à vos modèles. Avec un peu de chance, cela suffira pour que tout fonctionne pour vous.
Notez que ce sont des méthodes Python classiques. Ajoutons une méthode personnalisée, juste pour la démonstration :
import datetime
# ...
class Poll(models.Model):
# ...
def was_published_today(self):
return self.pub_date.date() == datetime.date.today()
Notez l'ajout de import datetime pour référencer le module datetime standard de Python.
Retournons au shell interactif de Python en exécutant à nouveau python manage.py shell :
>>> from mysite.polls.models import Poll, Choice
# Assurons-nous que notre ajout __unicode__() fonctionne.
>>> Poll.objects.all()
[<Poll: Quoi de neuf ?>]
# Django fournit une API de recherche dans la base de donnée très complète
# et entièrement pilotée par les mots-clés fournis en argument.
>>> Poll.objects.filter(id=1)
[<Poll: Quoi de neuf ?>]
>>> Poll.objects.filter(question__startswith='Quoi')
[<Poll: Quoi de neuf ?>]
# Récupérer le sondage dont l'année est 2007. Évidemment, si vous suivez ce
# tutoriel une année différente, adaptez-vous...
>>> Poll.objects.get(pub_date__year=2007)
<Poll: Quoi de neuf ?>
>>> Poll.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Poll matching query does not exist.
# La recherche sur la clé primaire est le cas le plus fréquent. Django
# fournit donc un raccourci pour les recherches exactes sur celle-ci.
# Ce qui suit est identique à Poll.objects.get(id=1)
>>> Poll.objects.get(pk=1)
<Poll: Quoi de neuf ?>
# Voyons si notre méthode personnalisée fonctionne.
>>> p = Poll.objects.get(pk=1)
>>> p.was_published_today()
False
# On ajoute au sondage des possibilités de choix. L'appel à create construit
# un nouvel objet choix, lance l'instruction INSERT, ajoute le choix à
# l'ensemble des choix possibles et renvoie le nouvel objet.
>>> p = Poll.objects.get(pk=1)
>>> p.choice_set.create(choice='Rien', votes=0)
<Choice: Rien>
>>> p.choice_set.create(choice='Le ciel', votes=0)
<Choice: Le ciel>
>>> c = p.choice_set.create(choice='Encore en train de coder', votes=0)
# Les objets choix ont une API pour accèder à l'objet sondage auquel ils
# sont reliés
>>> c.poll
<Poll: Quoi de neuf ?>
# Et réciproquement : les objets sondages ont accès aux objets choix.
>>> p.choice_set.all()
[<Choice: Rien>, <Choice: Le ciel>, <Choice: Encore en train de coder>]
>>> p.choice_set.count()
3
# L'API suit les relations automatiquement, aussi loin que nécessaire.
# Utilisez les doubles tirets de soulignement pour séparer les relations.
# Cela fonctionne avec la profondeur que vous souhaitez, il n'y a pas de
# limite.
# Trouver tous les choix pour tout sondage dont la pub_date est 2007.
>>> Choice.objects.filter(poll__pub_date__year=2007)
[<Choice: Rien>, <Choice: Le ciel>, <Choice: Encore en train de coder>]
# Supprimons un des choix. Utilisez delete() pour ça.
>>> c = p.choice_set.filter(choice__startswith='Encore en')
>>> c.delete()
Pour tous les détails sur l'API de base de données, voyez la référence de l'API de base de données (en).
Lorsque vous êtes familiarisés avec l'API, lisez la partie 2 de ce tutoriel pour faire fonctionner l'interface d'administration automatique de Django.
Nov 11, 2009