Repository with sources and generator of https://larlet.fr/david/ https://larlet.fr/david/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

article.md 37KB

title: Rédaction de votre première appli Django, partie 1 : Initialisation, création des modèles et API de la base de données slug: redaction-de-votre-premiere-appli-django-partie-1-initialisation-creation-des-modeles-et-api-de-la-base-de-donnees date: 2006-06-17 17:57:32 type: post vignette: images/logos/django.png contextual_title1: Le langage de template Django : Pour les auteurs de templates contextual_url1: 20060815-le-langage-de-template-django-pour-les-auteurs-de-templates contextual_title2: Comparaison de TurboGears et Django, deux frameworks web Python contextual_url2: 20060715-comparaison-de-turbogears-et-django-deux-frameworks-web-python contextual_title3: Rédaction de votre première appli Django, partie 4 : Conception d'un formulaire et vues génériques contextual_url3: 20060617-redaction-de-votre-premiere-appli-django-partie-4-conception-d-un-formulaire-et-vues-generiques

Apprenons par l'exemple.

À travers ce tutoriel, nous aborderons la création d'une application basique de sondage.

Cela consistera en deux parties:

  • Un site public qui permet aux internautes de voir les sondages et de voter.
  • Un site d'administration qui vous permet d'ajouter, modifier et supprimer un sondage.

Nous considèrerons que vous avez déjà Django d'installé. Vous pouvez tester si Django est installé en lançant l'interpréteur interactif Python et en tapant import django. Si cette commande s'exécute sans erreur, c'est que Django est bien installé.

Création d'un projet

Si vous utilisez Django pour la première fois, vous devrez faire attention à quelques options de la configuration initiale. En effet, vous aurez besoin d'auto-générer du code qui met en place un projet Django -- une configuration propre à chaque instance de Django, incluant la configuration de la base de données, les options spécifiques à Django et la configuration spécifique aux applications.

En ligne de commande, faites cd d'un répertoire où vous aimeriez conserver votre code, puis lancez la commande django-admin.py startproject monsite. Ceci va créer un répertoire monsite dans le répertoire courant.

(django-admin.py devrait être dans votre path système si vous avez installé Django via python setup.py. S'il n'est pas dans votre path, vous pouvez le trouver dans site-packages/django/bin, où site-packages est un sous-répertoire de votre installation Python. Faites un lien symbolique de django-admin.py quelque part dans votre path, typiquement /usr/local/bin.)

Où devrait-on mettre le code ?

Si vous avez connu le PHP, vous êtes probablement habitué à mettre le code dans le répertoire de documents du server Web (dans un endroit comme /var/www). Avec Django, ne faites pas ça. Ce n'est pas une bonne idée de mettre du code python dans votre répertoire de documents du serveur Web parce que vous prennez le risquez que l'on puisse voir votre code depuis le Web. Ce n'est pas bon d'un point de vue de la sécurité.

Mettez votre code dans un répertoire à l'extérieur du répertoire de documents, par exemple /home/moncode.

Jetons un œil à ce que startproject a créé:

monsite/
    __init__.py
    manage.py
    settings.py
    urls.py

Ces fichiers sont:

  • __init__.py: Un fichier vide que dit à Python que ce répertoire doit être considéré comme un paquetage Python. (En savoir plus sur les paquetages dans la documentation officielle de Python si vous êtes débutant en Python.)
  • manage.py: Un outil en ligne de commande que vous permet d'intéragir avec ce projet Django de différentes manières.
  • settings.py: Fichier de configuration de ce projet Django.
  • urls.py: Les déclarations d'URLs pour ce projet Django ; il s'agit d'une « table des matières » de votre site géré par Django.

Le serveur de développement

Vérifions que tout ceci fonctionne. Placez-vous dans le répertoire monsite, si vous ne l'avez pas déjà fait, lancez la commande python manage.py runserver. Vous verrez la trace d'exécution suivante dans votre terminal:

Validating models...
0 errors found.

Django version 0.95, using settings 'monsite.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).

Vous avez démarré le serveur de développement de Django, un serveur web léger écrit entièrement en Python. Nous l'avons intégré à Django pour que vous puissiez développer des choses rapidement, sans avoir à vous occuper de la configuration d'un serveur de production -- tel Apache -- jusqu'à ce que vous soyez prêt à passer en production.

À présent, c'est le bon moment pour noter : N'utilisez PAS ce serveur pour quoi que ce soit ressemblant à un environnement de production. C'est seulement destiné à une utilisation pendant le développement (Nous concevons des frameworks Web, pas des serveurs Web).

Maintenant que le serveur tourne, visitez la page http://127.0.0.1:8000/ avec votre navigateur Web. Vous verrez une page « Welcome to Django », dans un agréable bleu clair pastel. Ça marche !

Changement du port

Par défaut, la commande runserver démarre le serveur de développement sur le port 8000. Si vous voulez changer le port du serveur, passez-le en tant qu'argument à la ligne de commande. Par exemple, cette commande démarre le serveur sur le port 8080:

python manage.py runserver 8080

Une documentation complète sur le serveur de développement se trouve dans la documentation de django-admin.

Configuration de la base de données

Maintenant, éditez le fichier settings.py. C'est un module Python normal avec des variables de module représentant les options de configuration de Django. Modifiez ces options pour qu'elles correspondent à vos paramètres de connexion à votre base de données:

  • DATABASE_ENGINE -- Au choix parmi 'postgresql', 'mysql' ou 'sqlite3'. D'autres viendront bientôt.
  • DATABASE_NAME -- Le nom de votre base de données, ou le chemin complet (absolu) du fichier de base de données si vous utilisez SQLite.
  • DATABASE_USER -- Le nom d'utilisateur de la base de données (non utilisé pour SQLite).
  • DATABASE_PASSWORD -- Le mot de passe de la base de données (non utilisé pour SQLite).
  • DATABASE_HOST -- Le nom d'hôte sur lequel est votre base de données. Laissez une chaîne vide si votre serveur de base de données est sur la même machine physique (non utilisé pour SQLite).

Note

Si vous utilisez PostgreSQL ou MySQL, assurez-vous d'avoir créé une base de données à cette étape. Faites cela avec « CREATE DATABASE base_de_donnees; » à l'invite du client interactif de votre base de données.

Pendant que vous éditez settings.py, notez la présence de l'option INSTALLED_APPS vers la fin du fichier. Cette variable contient le nom de toutes les applications Django qui sont activées dans cette instance de Django. Les applis peuvent être utilisées dans de multiples projets, et vous pouvez les empaqueter et les distribuer pour que d'autres les utilisent dans leurs projets.

Par défaut, INSTALLED_APPS contient les applis suivantes, toutes sont fournies avec Django:

  • django.contrib.auth -- Un système d'authentification.
  • django.contrib.contenttypes -- Un framework pour les types de contenu.
  • django.contrib.sessions -- Un framework gérant les sessions.
  • django.contrib.sites -- Un framework pour gérer plusieurs sites avec une seule installation de Django.

Ces applications sont incluses par défaut car elles conviennent pour la plupart des cas.

Chacune de ces applications entraîne l'utilisation d'au moins une table de base de données, par conséquent, nous avons besoin de créer ces tables dans la base de données avant que nous puissions les utiliser. Pour ce faire, lancez la commande suivante:

python manage.py syncdb

La commande syncdb regarde l'option INSTALLED_APPS et crée toutes les tables de base de données nécessaires selon la configuration de la base de données dans votre fichier settings.py. Vous verrez un message pour chaque table que ça crée, et vous aurez une invite vous demandant si vous aimeriez créer un compte superutilisateur pour le système d'authentification. Continuez et faites-le.

Si cela vous intéresse, exécutez le client intéractif 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 nous avons dit plus haut, les applications par défaut sont incluses pour les cas courants, mais tout le monde n'en a pas forcément besoin. Si vous n'avez pas besoin d'une ou plusieurs d'entre elles (voire toutes), libre à vous de commenter ou supprimer la ou les lignes appropriées dans INSTALLED_APPS avant de lancer syncdb. La commande syncdb créera les tables uniquement pour les applis qui sont dans INSTALLED_APPS.

Création de modèles

Maintenant que notre environnement -- un "projet" -- est initialisé, vous pouvez commencer à travailler.

Chaque application que vous écrivez dans Django constitue un paquetage Python, quelque part dans votre Python path, qui suit une certaine convention. Django est fourni avec un utilitaire que génère automatiquement la structure basique du répertoire d'une appli, vous pouvez donc vous focaliser sur la rédaction du code plutôt que sur la création des répertoires.

Projets contre applis

Quelle est la différence entre un projet et une appli ? Une appli est une application web que fait quelque chose -- par exemple, un système de weblog, une base d'enregistrements publics ou une simple appli de sondage. Un projet est un ensemble de paramètres et d'applications pour un site Web particulier. Un projet peut contenir plusieurs applis. Une appli peut être dans plusieurs projets.

Dans ce tutoriel, nous allons créer notre appli de sondage dans le répertoire monsite, pour plus de simplicité. En conséquence, l'appli sera couplée au projet -- c'est-à-dire que le code Python dans l'appli de sondage réfèrera à monsite.polls. Plus tard dans le tutoriel, nous discuterons du découplage de vos applications pour les distribuer indépendamment.

Pour créer votre appli, assurez-vous que vous êtes dans le répertoire monsite et tapez la commande:

python manage.py startapp polls

Cela créera un répertoire polls, qui est décrit comme suit:

polls/
    __init__.py
    models.py
    views.py

Cette structure du répertoire va accueillir l'application de sondage.

La première étape dans la rédaction d'une appli Web utilisant la base de données est de définir vos modèles -- essentiellement, la description de votre base de données, avec des méta-données additionnelles.

Philosophie

Un modèle est la seule et définitive source de donnée à propos de vos données. Il contient les champs essentiels et les comportements des données que vous stockez. Django suit le Principe DRY. Le but est de définir votre modèle de données dans un endroit et d'en faire dériver tout le reste automatiquement.

Dans notre simple appli de sondage, nous allons créer deux modèles: polls et choices. Un sondage est constitué d'une question et d'une date de publication. Un choix a deux champs: le libellé du choix et le nombre de votes pour ce choix. Chaque choix est associé à un sondage.

Ces concepts sont représentés par de simples classes Python. Éditez le fichier polls/models.py pour qu'il ressemble à ça:

from django.db import models

class Poll(models.Model):
    question = models.CharField(maxlength=200)
    pub_date = models.DateTimeField('Date de publication')

class Choice(models.Model):
    poll = models.ForeignKey(Poll)
    choice = models.CharField(maxlength=200)
    votes = models.IntegerField()

Le code est clair et concis. Chaque modèle est représenté par une classe qui étend django.db.models.Model. Chaque molèle a un certain nombre d'attributs de classe, chacun représentant un champ de base de données dans le modèle.

Chaque champ est représenté par l'instance d'une classe models.*Field -- par exemple, models.CharField pour les champs de chaîne de caractères et models.DateTimeField pour les dates/heures. Ceci décrit à Django quel type de données est contenu dans chaque champs.

Le nom de chaque instance de models.*Field (par exemple question ou pub_date ) est le nom du champ, dans un format informatique. Vous utiliserez cette valeur dans votre code Python, et votre base de données l'utilisera comme un nom de colonne.

Vous pouvez définir en premier argument facultatif Field un nom informel, plus facilement compréhensible par un lecteur humain. Celui-ci est utilisé dans des parties introspective de Django et il contribue aussi à la documentation du code. Si ce champ n'est pas fourni, Django utilisera alors le nom informatique. Dans cet exemple, nous avons seulement défini un nom informel pour Poll.pub_date. Pour tous les autres champs de ce modèle, le nom informatique du champs est suffisamment explicite pour rester lisible.

Quelques classes *Field requièrent des éléments. CharField, par exemple, requiert que vous lui donniez une longueur maximale maxlength. Ce n'est pas seulement utilisé dans le schéma de la base de données, mais également dans la validation, comme nous le verrons bientôt.

Enfin, notez que la relation est définie en utilisant models.ForeignKey. Ça dit à Django que chaque choix Choice est lié à un unique sondage Poll. Django supporte toutes les relations communes des bases de données: n vers 1, n vers m et 1 vers 1.

Activation des modèles

Ce petit bout de code de modèle donne à Django beaucoup d'informations. Avec lui, Django est capable de:

  • Créer le schéma de base de données (les instructions CREATE TABLE) pour cette appli.
  • Créer une API en Python d'accès à la base de données afin d'accéder aux objets Poll et Choice.

Mais avant, nous avons besoin de dire à notre projet que l'application polls est installée.

Philosophie

Les applis Django sont « pluggables » : Vous pouvez utiliser une appli dans de nombreux projets, et vous pouvez distribuer des applis, parce qu'elles ne doivent pas dépendre d'une installation Django donnée.

Éditez à nouveau le fichier settings.py, et changez l'option INSTALLED_APPS pour inclure la chaîne 'monsite.polls'. Ce qui devrait ressembler à ça:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'monsite.polls'
)

Maintenant Django sait que monsite inclue l'appli polls. Lançons une autre commande:

python manage.py sql polls

Vous devriez voir ce qui suit (les instructions SQL CREATE TABLE pour l'appli polls):

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 ceci:

  • Le nom des tables est généré automatiquement en combinant le nom de l'appli (polls) avec le nom en minuscule du modèle -- poll et choice. (Vous pouvez changer ce comportement.)
  • Les clés primaires (IDs) sont ajoutées automatiquement. (Vous pouvez aussi le changer.)
  • Par convention, Django ajoute "_id" à nom de champ de la clé étrangère. Oui, vous pouvez également le changer.
  • La relation de la clé étrangère est faite explicitement par une clause REFERENCES.
  • Le code est rédigé pour la base de données que vous employez, donc les types de champ spécifiques à chaque base de données, tel que auto_increment (MySQL), serial (PostgreSQL), ou integer primary key (SQLite) sont gérés pour vous automatiquement. Même chose pour les quotes de noms de champs -- par exemple, l'utilisation de doubles ou simples quotes. L'auteur de ce tutoriel utilise PostgreSQL, donc les traces d'exécution de l'exemple sont dans la syntaxe PostgreSQL.
  • La commande sql ne lance en fait pas le code SQL dans votre base de données - il l'affiche juste à l'écran pour que vous puissiez voir quel code SQL est requis d'après Django. Si vous aviez voulu, nous auriez pu copier et coller ce code SQL dans l'invite interactive de votre base de données. Cependant, comme nous le verrons d'ici peu, Django fournit une moyen plus simple d'éxecuter le SQL dans la base de données.
Si vous êtes intéressé, lancez aussi les commandes suivantes :
  • python manage.py validate polls -- Vérifie s'il n'y a pas d'erreurs dans la construction de vos modèles.
  • python manage.py sqlinitialdata polls -- Affiche toutes les données initiales requises pour le framework d'administration de Django et pour vos modèles.
  • python manage.py sqlclear polls -- Affiche les instructions DROP TABLE nécessaires pour cette appli, selon les table qui existent déjà dans votre base de données (s'il y en a).
  • python manage.py sqlindexes polls -- Affiche les instructions CREATE INDEX pour cette appli.
  • python manage.py sqlall polls -- Une combinaison de tous les codes SQL des commandes 'sql', 'sqlinitialdata', et 'sqlindexes'.

L'examen de la trace d'exécution de ces commandes peut vous aider à comprendre ce qui se passe en fait en bas-niveau.

À présent, lancez à nouveau syncdb pour créer ces tables du modèles dans votre base de données:

python manage.py syncdb

La commande syncdb exécute le code sql de 'sqlall' dans votre base de données pour toutes les applis de INSTALLED_APPS qui n'existent pas encore dans votre base de données. Ça crée toutes les tables, initie les données et indexes pour toutes les applis que vous avez ajouté dans votre projet depuis la dernière fois que vous avez lancé syncdb. syncdb peut être appelé aussi souvent que vous le souhaitez, et ça ne créera que les tables qui n'existaient pas auparavant.

Lisez la documentation de django-admin.py pour des informations complètes sur ce que l'outil manage.py peut faire.

Jouons avec l'API

Maintenant, jetons un œil au shell Python interactif et jouons avec l'API libre que Django nous fournit. Pour invoquer le shell Python, utilisez cette commande:

python manage.py shell

Nous utilisons celle-ci au lieu de simplement taper « python » parce que manage.py définit l'environnement du projet pour vous. « Définir l'environnement » signifie deux choses:

  • Insertion de monsite dans sys.path. Par flexibilité, plusieurs parties de Django se référent aux projets à l'aide de la notation Python de chemins séparés par des points (par exemple, 'monsite.polls.models'` ). Et pour que ça marche, le paquetage monsite doit être dans sys.path.

    Nous avons déjà vu un exemple de cela : l'option INSTALLED_APPS est une liste de paquetages utilisant la notation de chemins séparés par des points.

  • Définition de la variable d'environnement DJANGO_SETTINGS_MODULE, qui indique à Django le chemin vers votre fichier settings.py.

Outrepasser manage.py

Si vous préférez ne pas utiliser manage.py, pas de problème. Vérifiez juste que monsite est à la racine du path Python (c'est-à-dire, import monsite fonctionne) et définissez la variable d'environnement DJANGO_SETTINGS_MODULE à monsite.settings.

Pour plus d'informations sur tout cela, lisez la documentation de django-admin.py.

Une fois que vous êtes dans le shell, explorez l'API pour la base de données:

# Importe les classes de modèle que nous venons d'écrire.
>>> from monsite.polls.models import Poll, Choice

# Aucun sondage n'est dans le système pour l'instant.

>>> Poll.objects.all()
[]

# Crée un nouveau sondage Poll.
>>> from datetime import datetime
>>> p = Poll(question="Quoi de neuf ?", pub_date=datetime.now())

# Sauvegarde l'objet dans la base de données.
# Vous devez appeler save() explicitement.
>>> p.save()

# Maintenant il a un ID. Notez que ça pourrait afficher "1L" au lieu de "1",
# cela dépend de la base de données que vous utilisez. Ce n'est pas un bug ;
# ça signifie juste que le backend de votre base de données préfère
# retourner les entiers comme des objets de type entiers longs en Python.
>>> p.id
1

# Accède aux colonnes de base de données via les attributs Python.

>>> p.question
"Quoi de neuf ?"
>>> p.pub_date
datetime.datetime(2005, 7, 15, 12, 00, 53)

# Change les valeurs en modifiant les attributs, puis en appelant save().
>>> p.pub_date = datetime(2005, 4, 1, 0, 0)
>>> p.save()

# objects.all() affiche tous les sondages de la base de données.
>>> Poll.objects.all()
[<Poll: Poll object>]

Attendez une minute. <Poll: Poll object> est, à vrai dire, une représentation qui n'apporte rien sur l'objet. Corrigeons cela en éditant le modèle des sondages (dans le fichier polls/models.py) et en ajoutant une méthode __str__() aux classes Poll et Choice:

class Poll(models.Model):
    # ...
    def __str__(self):
        return self.question

class Choice(models.Model):
    # ...
    def __str__(self):
        return self.choice

Il est important d'ajouter les méthodes __str__() dans vos modèles, pas seulement pour votre propre bien-être lorsque vous utilisez la console interactive, mais aussi parce que les représentations d'objets sont utilisées à travers l'interface d'administration auto-générée de Django.

Notez que ce sont des méthodes standards de Python. Ajoutons une méthode perso, juste pour la démo:

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 standard de Python datetime.

Revenons au shell Python interactif en lançant à nouveau python manage.py shell:

>>> from monsite.polls.models import Poll, Choice

# Vérifie que notre nouvelle méthode __str__() fonctionne.
>>> Poll.objects.all()
[<Poll: Quoi de neuf ?>]

# Django fournit une riche API de recherche dans la base de données qui est
# entièrement gérée par des arguments mot-clés.
>>> Poll.objects.filter(id=1)
[<Poll: Quoi de neuf ?>]

>>> Poll.objects.filter(question__startswith='Quoi')
[<Poll: Quoi de neuf ?>]

# Récupére le sondage dont l'année est 2005. Bien sûr, si vous suivez ce
# tutoriel dans une autre année, remplacez par la valeur appropriée.
>>> Poll.objects.get(pub_date__year=2005)
<Poll: Quoi de neuf ?>

>>> Poll.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Poll matching query does not exist.

# La recherche par clé primaire est le cas le plus courant, donc Django
# fournit un raccourci pour les recherches exactes sur clé primaire.
# Ce qui suit est identique à Poll.objects.get(id=1).
>>> Poll.objects.get(pk=1)
<Poll: Quoi de neuf ?>

# Vérifie que notre méthode perso fonctionne.

>>> p = Poll.objects.get(pk=1)
>>> p.was_published_today()
False

# Donne une liste de choix Choice au sondage Poll. L'appel à create
# construit un nouvel objet choice, fait l'instruction INSERT , ajoute le
# choix dans l'ensemble des choix disponibles et retourne le nouvel objet
# Choice.
>>> p = Poll.objects.get(pk=1)
>>> p.choice_set.create(choice='Pas grand chose', votes=0)
<Choice: Pas grand chose>
>>> p.choice_set.create(choice='Le ciel', votes=0)
<Choice: Le ciel>
>>> c = p.choice_set.create(choice='Toujours en train de coder', votes=0)

# Les objets Choice ont une API d'accès aux objets Poll qui leur sont liés.
>>> c.poll

<Poll: Quoi de neuf ?>

# Et vice-versa: les objets Poll ont accès aux objets Choice.
>>> p.choice_set.all()
[<Choice: Pas grand chose>, <Choice: Le ciel>, <Choice: Toujours en train de coder>]
>>> p.choice_set.count()
3

# L'API suit automatiquement les relations aussi loin que vous en avez
# besoin. Utilisez les doubles underscores pour séparer les relations.
# Ça fonctionne sur autant de niveaux de profonteur que vous voulez. Il n'y
# a pas de limite. Trouve tous les choix Choice pour n'importe quel sondage
# dont le pub_date est 2005.
>>> Choice.objects.filter(poll__pub_date__year=2005)
[<Choice: Pas grand chose>, <Choice: Le ciel>, <Choice: Toujours en train de coder>]

# Supprimons un des choix. Utilisez delete() pour se faire.

>>> c = p.choice_set.filter(choice__startswith='Toujours en train')
>>> c.delete()

Pour les détails complets au sujet de l'API de la base de données, lisez notre référence de l'API de base de données.

Quand vous vous serez familiarisé avec l'API, lisez la partie 2 de ce tutoriel pour voir le fonctionnement de l'interface d'administration automatique de Django.

Vous pouvez maintenant retourner à la page d'accueil des traductions de la documentation de Django.

Cette traduction correspond à la révision 3589 (post 0.95).