Ajout des modèles à notre application

Cette page vous apprendra à créer des modèles pour une application Django. Avant de commencer, assurez-vous de connaître MVC et de savoir ce qu'est un modèle…

Les modèles Django

Comme avec beaucoup de frameworks web, les modèles Django sont des classes qui héritent d'une classe du framework (classe qui s'appelle… Model !). En faisant hériter vos modèles de cette fameuse classe, vous leur conférez, de facto, toutes les propriétés et méthodes relatives aux modèles (gestion de l'ORM, etc.).

Syntaxe de déclaration d'un modèle

Vous l'aurez compris, c'est dans le fichier models.py de notre application que nous allons créer tous nos modèles. Voici la syntaxe :

models.py
from django.db import models

class MonModel(models.Model):
    """
    La doc de mon modèle.
    """
    un_champ_texte = models.CharField(max_length=150)

Les programmeurs Java seront peut-être surpris de voir que nous créons plusieurs classes (en l’occurrence, plusieurs modèles) dans le même fichier models.py : ce n'est pas un problème en Python ! Sachez simplement que si par la suite, notamment sur une application de grande taille, vous souhaitez diviser vos fichiers de modèles en plusieurs fichiers, c'est tout à fait possible.

Types de champs disponibles

En créant un modèle Django, nous allons utiliser le système d'ORM du framework. En d'autres termes, Django propose quelques types de champs (~ d'attributs) disponibles pour utilisation dans nos modèles, qu'il se chargera de mapper automatiquement avec les champs de base de données. En voici une liste non-exhaustive :

NomDescription
CharFieldUn champ de texte, typiquement mappé vers un « VARCHAR » en BDD.
TextFieldUn champ de texte long, typiquement mappé vers un « TEXT » en BDD.
ForeignKeyUne référence à un objet d'un autre modèle. En BDD, il est représenté par un entier désignant l'ID de la ligne cible.
ManyToManyFieldUne référence à plusieurs objets d'un autre modèle. En BDD, il est représenté à l'aide d'une table d'association.
BooleanFieldUn champ booléan (vrai ou faux).
URLFieldUn champ de texte représentant une URL, typiquement mappé vers un « VARCHAR » en BDD.
SlugFieldUn champ de texte représentant un slug, c'est à dire une chaîne de caractère destinée à être utilisée dans une URL.
IntegerFieldUn nombre entier.
DateTimeFieldUne date et une heure.

Nous n'allons pas lister ici tous les champs qu'il est possible d'utiliser dans un modèle. Une liste exhaustive est disponible sur la documentation officielle de Django, section Model field reference.

Chaque type de champ admet un certain nombre de paramétrages, que Django appelle des options. Nous n'allons pas non-plus tous les lister, mais voici les plus utilisés :

  • null=True|False : Permet de spécifier si le champ correspondant en BDD peut être NULL ou pas.
  • blank=True|False : Permet de spécifier si, dans les formulaires de l'application, le champ peut être laissé vide ou pas.
  • max_length=<int> : Permet de spécifier la longueur maximale d'un CharField (généralement, la limite est de 255 caractères)
  • default=<int|str|boolean...> : Permet de spécifier une valeur par défaut pour le champ

Voici un exemple d'utilisation de ces options dans le cadre de la déclaration d'un modèle :

from django.db import models

class MonModel(models.Model):
    un_champ_texte = models.CharField(max_length=150, null=True, blank=True, default="Coucou")

Modèles de notre application

OK, nous connaissons maintenant les principales caractéristiques de modèles et la syntaxe de leur déclaration.

Nous pouvons à présent créer une première version de nos modèles :

miage_scrum/chistera/models.py
# -*-coding: UTF-8-*-
from django.db import models
from django.contrib.auth.models import User

class Team(models.Model):
    """
    Une équipe scrum est un ensemble de personnes qui travaillent sur un projet.
    """
    members = models.ManyToManyField(User)
    name = models.CharField(max_length=150)

class Project(models.Model):
    """
    La représentation d'un projet dans le système.
    Un projet est pris en charge par une équipe.
    """
    team = models.ForeignKey(Team)
    name = models.CharField(max_length=150)

class ProductBacklog(models.Model):
    """
    Un backlog produit Scrum contient un ensemble de user stories.
    Chaque backlog est systématiquement rattaché à un projet.
    """
    team = models.ForeignKey(Team)
    name = models.CharField(max_length=150)

class Sprint(models.Model):
    """
	Le sprint est une itération en Scrum, réalisée par une équipe.
	Dand un sprint, une équipe peut travailler sur plusieurs projets.
    """
    team = models.ForeignKey(Team)
    begin_date = models.DateTimeField()
    end_date = models.DateTimeField()

class UserStory(models.Model):
    """
    Une user story est une demande client.
    """
    product_backlog = models.ForeignKey(ProductBacklog)
    name = models.CharField(max_length=255)
    description = models.TextField()

Création des tables de base de données

Nous avons à présent de jolis modèles, mais rien pour stocker les données qui en découleront. Pour pallier ce problème, nous allons faire dans le classique : nous utiliserons une base de données relationnelle.

Pour éviter d'avoir à installer un serveur de BDD comme PostgreSQL ou MySQL, nous allons utiliser SQLite. Sachant que puisque nous utilisons un ORM, nous serons libre, plus tard, notamment si le projet obtient le succès qu'il mérite (☺), de switcher très simplement vers un autre SGBD, en modifiant juste la configuration de notre projet.

Pour utiliser SQLite, nous n'avons rien de spécial à faire, si ce n'est de fournir le nom du fichier de BDD à Django dans notre fichier de configuration.

Si vous ne connaissez pas SQLite, vous en trouverez une description simple et rapide ici : Sqlite, une base de données parfaite pour les petits projets. Retenez simplement que SQLite est un SGBD qui n'est pas client-serveur, mais fonctionne avec un simple fichier dans lequel sont stockées vos données. C'est simple et rapide !

Modification du fichier settings.py

Pour préciser à Django que nous souhaitons utiliser SQLite, nous allons modifier le fichier settings.py de notre projet. Ouvrez le fichier, cherchez la variable DATABASES, et modifiez là pour qu'elle ressemble à ceci :

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'scrum_db',
    }
}

Tant que nous sommes sur le fichier settings.py, modifions également la section INSTALLED_APPS, pour préciser à Django que nous souhaitons aussi utiliser, dans ce projet, notre application chistera :

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'chistera'
)

Vous remarquez que notre projet utilise, par défaut, d'autres applications. Ce sont des applications fournies par le framework lui-même, pour gérer diverses problématiques comme l'authentification des utilisateurs, les sessions, etc. Nous y ajoutons simplement la notre !

Sauvegardez le fichier.

Si vous êtes curieux, vous aurez remarqué qu'en arrière plan (visible sur votre terminal), le serveur de développement redémarre automatiquement quand vous modifiez un fichier de code de votre application. De la sorte, votre appli est toujours prête à être testée, et toujours à jour !

Syncdb

OK, Django sait maintenant où écrire ses données !

Nous allons maintenant lui demander de créer les tables de la base de données pour nous, à partir des informations que nous lui avons fournies dans les modèles de nos applications (en l’occurrence, de notre application, puisque notre projet n'en comporte qu'une pour le moment).

Nous allons encore une fois utiliser la commande python manage.py, avec l'argument syncdb :

$ python manage.py syncdb

Django commence alors à créer les tables de la base de données, et vous demande quelques informations pour y insérer quelques données :

Creating tables ...
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_groups
Creating table auth_user_user_permissions
Creating table auth_user
Creating table django_content_type
Creating table django_session
Creating table django_site
Creating table chistera_team
Creating table chistera_project
Creating table chistera_productbacklog
Creating table chistera_sprint
Creating table chistera_userstory

You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (leave blank to use 'pascal'):
Email address: contact@formation-django.fr
Password:
Password (again):
Superuser created successfully.
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)

OK, notre base de données est à présent créée, et comporte les tables nécessaires au fonctionnement de notre application. Si vous listez le contenu du répertoire de votre projet, vous devez y voir un nouveau fichier, nommé scrum_db. C'est notre base de données SQLite !

Vous avez remarqué que Django a créé d'autres tables que celles relatives à notre application ! Ce sont les tables utiles aux autres applications mentionnées dans notre fichier settings.py. Rien d'alarmant donc…

Par curiosité, vous pouvez ouvrir votre base de données SQLite pour voir ce qu'elle contient. Plusieurs outils existent : à moindre frais, vous pouvez utiliser le plugin Firefox SQLite Manager !

Instaler SQLite Manager pour Firefox

Base de données SQLite application Django
La BDD SQLite de notre projet ouverte avec l'outil SQLite Manager pour Firefox

Modèles, BDD : check !

Notre projet et notre application prennent forme ! Nous allons maintenant voir comment disposer, en quelques secondes, d'une interface d'administration puissante permettant d'éditer nos données : c'est l'objet du tutoriel sur le scaffolding avec Django.

Testez vos connaissances

Une application Django doit-elle nécessairement définir des modèles ?
  • Oui
  • Non

Gardez en tête que l'on utilise énormément les applications en Django, y compris pour réaliser des choses qui ne manipules pas de données métier stockées en BDD. Vous n'êtes donc pas obligé de définir des modèles dans une app Django : ceci dit, dans 95% des applications, on définit des modèles !

Qu'est-ce qu'un modèle ?
  • C'est une application réutilisable qui pourra être copiée pour en créer une autre.
  • C'est une classe qui définit un type d'objet métier ainsi que les opérations qu'il est possible de réaliser sur ces objets.
  • C'est une fonction Python qui permet de mettre en œuvre un contexte dans une vue.
Peut-on définir plusieurs classes de modèle dans le fichier models.py ?
  • Non, c'est une aberration : c'est impossible de déclarer plusieurs classes dans un fichier comme on l'a appris en cours de Java.
  • Oui

Que signifie le code suivant ?

class Page(models.Model):
    author = models.ForeignKey(User, null=True, blank=True, verbose_name="auteur")
    title = models.CharField(max_length=255, blank=True)
  • Il s'agit de la déclaration d'un modèle Django.
  • La classe models.Model est de type Page.
  • La classe Page possède deux méthodes.
  • Le modèle Page possède deux attributs, author et title.
  • Le champ title du modèle Page pourra avoir la valeur NULL en base de données.

Les modèles d'une application Django héritent systématiquement de la classe models.Model.

Ne confondez pas null et blank. null permet de dire qu'un champ pourra avoir la valeur NULL en BDD, alors que blank signifie que le champ pourra être laissé vide dans l'interface d'administration (mais sera tout même initialisé avec une valeur vide ou 0 si null n'est pas autorisé !).

À quoi sert la commande de management Django syncdb ?
  • Comme son nom l'indique, elle permet de synchroniser les déclarations de modèles avec les structures de tables de BDD : création et mise à jour.
  • Elle permet de créer en base de données les tables nécessaires à la persistance des modèles des applications d'un projet Django.
  • Elle permet de lancer le serveur de développement Django.
  • syncdb n'est pas une commande de management Django.
J'ai exécuté syncdb, aucune erreur mais les tables correspondant à mes modèles applicatifs n'ont pas été créées en BDD. Quelles sont les causes possibles ?
  • Je n'ai pas déclaré mon ou mes applications dans le fichier settings.py de mon projet.
  • Le fichier settings.py de mon application est erroné.
  • Aucune de mes applications ne définit de modèle.
Quand ai-je intérêt à utiliser une base de donnée MySQL, Oracle ou Postgres plutôt que SQLite dans un projet Django ?
  • Quand mes applications génèrent de nombreuses requêtes concurrentes de mise à jour de données.
  • Si j'ai plus d'argent à dépenser car ces technologies sont onéreuses.
  • Quand j'ai besoin de plus de simplicité de mise en œuvre et de gestion.
  • Globalement, lorsque le site en question a une très forte fréquentation.