introduction
Dans le didacticiel précédent, «https://www.digitalocean.com/community/tutorials/how-to-create-a-django-app-and-connect-it-to-a-database[Comment créer une application Django et connectez-le à une base de données] », nous avons expliqué comment créer une base de données MySQL, comment créer et démarrer une application Django et comment la connecter à une base de données MySQL.
Dans ce tutoriel, nous allons créer les Djangomodels qui définissent les champs et les comportements des données de l'application Blog que nous stockerons. Ces modèles mappent les données de votre application Django à la base de données. C'est ce que Django utilise pour générer les tables de base de données via leur API ORM (Object Relational Mapping) appelée "modèles".
Conditions préalables
MySQL doit être installé sur un serveur Ubuntu 16.04 et une connexion à une base de données doit également être configurée avec votre application Django. Si vous ne l'avez pas déjà fait, référez-vous à la deuxième partie de la série Django, “https://www.digitalocean.com/community/tutorials/how-to-create-a-django-app-and-connect- it-to-a-database [Comment créer une application Django et la connecter à une base de données]. ”
[[step-1 -—- create-django-application]] == Étape 1 - Créer une application Django
Pour rester fidèle à la philosophie de modularité de Django, nous créerons une application Django dans notre projet contenant tous les fichiers nécessaires à la création du site Web du blog.
Commencez par activer votre environnement virtuel Python:
cd ~/my_blog_app
. env/bin/activate
cd blog
A partir de là, exécutons cette commande:
python manage.py startapp blogsite
À ce stade, vous aurez la structure de répertoire suivante pour votre projet:
my_blog_app/
└── blog
├── blog
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ ├── settings.cpython-35.pyc
│ │ ├── urls.cpython-35.pyc
│ │ └── wsgi.cpython-35.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── blogsite
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── manage.py
Le fichier sur lequel nous allons nous concentrer pour ce didacticiel sera le fichiermodels.py
.
[[step-2 -—- add-the-posts-model]] == Étape 2 - Ajouter le modèle de posts
Nous devons d'abord ouvrir et éditer le fichiermodels.py
afin qu'il contienne le code pour générer un modèlePost
. Un modèlePost
contient les champs de base de données suivants:
-
title
- Le titre du billet de blog. -
slug
- Où les URL valides sont stockées et générées pour les pages Web. -
content
- Le contenu textuel de l'article de blog. -
created_on
- La date à laquelle le message a été créé. -
author
- La personne qui a rédigé le message.
Maintenant, changez les répertoires dans lesquels le fichiermodels.py
est contenu.
cd ~/my_blog_app/blog/blogsite
Utilisez la commandecat
pour afficher le contenu du fichier dans votre terminal.
cat models.py
Le fichier doit avoir le code suivant, qui importe les modèles, ainsi qu'un commentaire décrivant ce qui doit être placé dans ce fichiermodels.py
.
models.py
from django.db import models
# Create your models here.
À l'aide de votre éditeur de texte ou IDE préféré, ajoutez le code suivant au fichiermodels.py
. Nous utiliseronsnano
comme éditeur de texte. Mais, vous pouvez utiliser ce que vous préférez.
nano models.py
Dans ce fichier, le code pour importer les modèles API est déjà ajouté, nous pouvons continuer et supprimer le commentaire qui suit. Ensuite, nous importerons lesslugify
pour générer des slugs à partir de chaînes, et lesUser
de Django pour l'authentification comme ceci:
models.py
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
Ensuite, ajoutez la méthode de classe sur la classe de modèle que nous appelleronsPost
, avec les champs de base de données suivants,title
,slug
,content
,created_on
et author
.
models.py
...
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=255)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
author = models.TextField()
Ensuite, nous allons ajouter des fonctionnalités pour la génération de l'URL et la fonction pour enregistrer le message. Ceci est crucial, car cela crée un lien unique pour correspondre à notre article unique.
models.py
...
@models.permalink
def get_absolute_url(self):
return ('blog_post_detail', (),
{
'slug': self.slug,
})
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
Maintenant, nous devons indiquer au modèle comment les articles doivent être commandés et affichés sur la page Web. La logique pour cela sera ajoutée à une classe interne imbriquéeMeta
. La classeMeta
contient généralement une autre logique de modèle importante qui n'est pas liée à la définition de champ de base de données.
models.py
...
class Meta:
ordering = ['created_on']
def __unicode__(self):
return self.title
Enfin, nous ajouterons le modèleComment
à ce fichier. Cela implique l'ajout d'une autre classe nomméeComment
avecmodels.Models
dans sa signature et les champs de base de données suivants définis:
-
name
- Le nom de la personne qui publie le commentaire. -
email
- L'adresse e-mail de la personne qui publie le commentaire. -
text
- Le texte du commentaire lui-même. -
post
- Le message avec lequel le commentaire a été fait. -
created_on
- L'heure à laquelle le commentaire a été créé.
models.py
...
class Comment(models.Model):
name = models.CharField(max_length=42)
email = models.EmailField(max_length=75)
website = models.URLField(max_length=200, null=True, blank=True)
content = models.TextField()
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)
Une fois terminé, votre fichiermodels.py
complet devrait ressembler à ceci:
models.py
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=255)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
author = models.TextField()
@models.permalink
def get_absolute_url(self):
return ('blog_post_detail', (),
{
'slug': self.slug,
})
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
class Meta:
ordering = ['created_on']
def __unicode__(self):
return self.title
class Comment(models.Model):
name = models.CharField(max_length=42)
email = models.EmailField(max_length=75)
website = models.URLField(max_length=200, null=True, blank=True)
content = models.TextField()
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)
Assurez-vous de sauvegarder et de fermer le fichier.
Une fois le fichiermodels.py
configuré, nous pouvons continuer à mettre à jour notre fichiersettings.py
.
[[step-3 -—- update-settings]] == Étape 3 - Mettre à jour les paramètres
Maintenant que nous avons ajouté des modèles à notre application, nous devons informer notre projet de l'existence de l'applicationblogsite
que nous venons d'ajouter. Nous faisons cela en l'ajoutant à la sectionINSTALLED_APPS
danssettings.py
.
Accédez au répertoire où réside votresettings.py
.
cd ~/my_blog_app/blog/blog
De là, ouvrez votre fichiersettings.py
, avec nano, par exemple, en utilisant la commandenano settings.py
.
Avec le fichier ouvert, ajoutez votre applicationblogsite
à la sectionINSTALLED_APPS
du fichier, comme indiqué ci-dessous.
settings.py
# Application definition
INSTALLED_APPS = [
'blogsite',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
Avec l'applicationblogsite
ajoutée, vous pouvez enregistrer et quitter le fichier.
Nous sommes maintenant prêts à appliquer ces changements.
[[step-4 -—- make-migrations]] == Étape 4 - Effectuer des migrations
Avec nos modèlesPost
etComment
ajoutés, l'étape suivante consiste à appliquer ces modifications afin que notre schéma de base de donnéesMySQL
les reconnaisse et crée les tables nécessaires.
Jetons un œil aux tables qui existent déjà dans notre base de donnéesblog_data
.
Pour ce faire, nous devons nous connecter au serveur MySQL.
[.note] #Note: Dans cet exemple, nous utiliserons le nom d'utilisateurroot
sans mot de passe, mais vous devriez utiliser le nom d'utilisateur et le mot de passe que vous avez définis pour MySQL.
#
mysql blog_data -u root
Vous remarquerez que si vous tapez la commandeSHOW DATABASES;
, vous verrez ce qui suit:
Output+--------------------+
| Database |
+--------------------+
| information_schema |
| blog_data |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
Nous examinerons la base de donnéesblog_data
et afficherons les tables qui existent déjà, le cas échéant.
USE blog_data;
Ensuite, listez les tables qui existent dans la base de donnéesblog_data
:
SHOW TABLES;
OutputEmpty set (0.00 sec)
Pour l'instant, aucune table n'est affichée car nous n'avons encore effectué aucune migration. Cependant, lorsque nous effectuons des migrations, les tables générées par Django seront affichées.
Nous allons maintenant procéder aux migrations qui appliquent les modifications que nous avons apportées dansmodels.py
.
Fermez MySQL avecCTRL
+D
.
Tout d'abord, nous devons regrouper les modifications de notre modèle dans des fichiers de migration individuels à l'aide de la commandemakemigrations
. Ces fichiers sont similaires à ceux decommits
dans un système de contrôle de version commegit
.
Maintenant, si vous accédez à~/my_blog_app/blog/blogsite/migrations
et exécutezls
, vous remarquerez qu’il n’existe qu’un fichier__init__.py
. Cela changera une fois que nous aurons ajouté les migrations.
Accédez au répertoire du blog en utilisantcd
, comme ceci:
cd ~/my_blog_app/blog
python manage.py makemigrations
Vous devriez alors voir la sortie suivante dans la fenêtre de votre terminal:
OutputMigrations for 'blogsite':
blogsite/migrations/0001_initial.py
- Create model Comment
- Create model Post
- Add field post to comment
Rappelez-vous, lorsque nous avons navigué vers/~/my_blog_app/blog/blogsite/migrations
et qu'il n'y avait que le fichier__init__.py
? Si nous retournons maintenantcd
dans ce répertoire, nous verrons que deux choses ont été ajoutées,__pycache__
et0001_initial.py
. Le fichier0001_initial.py
a été généré automatiquement lorsque vous avez exécutémakemigrations
. Un fichier similaire sera généré chaque fois que vous exécuterezmakemigrations
.
Exécutezless 0001_initial.py
si vous souhaitez voir ce que contient le fichier.
Naviguez maintenant vers~/my_blog_app/blog
.
Puisque nous avons fait un fichier de migration, nous devons appliquer les modifications que ces fichiers décrivent à la base de données en utilisant la commandemigrate
. Mais voyons d'abord quelles migrations actuelles existent, à l'aide de la commandeshowmigrations
.
python manage.py showmigrations
Outputadmin
[ ] 0001_initial
[ ] 0002_logentry_remove_auto_add
auth
[ ] 0001_initial
[ ] 0002_alter_permission_name_max_length
[ ] 0003_alter_user_email_max_length
[ ] 0004_alter_user_username_opts
[ ] 0005_alter_user_last_login_null
[ ] 0006_require_contenttypes_0002
[ ] 0007_alter_validators_add_error_messages
[ ] 0008_alter_user_username_max_length
[ ] 0009_alter_user_last_name_max_length
blogsite
[ ] 0001_initial
contenttypes
[ ] 0001_initial
[ ] 0002_remove_content_type_name
sessions
[ ] 0001_initial
Vous remarquerez la migration que nous venons d'ajouter pourblogsite
, qui contient la migration0001_initial
pour les modèlesPost
etComment
.
Voyons maintenant les instructionsSQL
qui seront exécutées une fois que nous aurons effectué les migrations, à l'aide de la commande suivante. Il prend comme argument la migration et le titre de la migration:
python manage.py sqlmigrate blogsite 0001_initial
Comme vous pouvez le voir ci-dessous, il s’agit de la requête SQL réelle effectuée en coulisse.
BEGIN;
--
-- Create model Comment
--
CREATE TABLE `blogsite_comment` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(42) NOT NULL, `email` varchar(75) NOT NULL, `website` varchar(200) NULL, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL);
--
-- Create model Post
--
CREATE TABLE `blogsite_post` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `title` varchar(255) NOT NULL, `slug` varchar(255) NOT NULL UNIQUE, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `author` longtext NOT NULL);
--
-- Add field post to comment
--
ALTER TABLE `blogsite_comment` ADD COLUMN `post_id` integer NOT NULL;
ALTER TABLE `blogsite_comment` ADD CONSTRAINT `blogsite_comment_post_id_de248bfe_fk_blogsite_post_id` FOREIGN KEY (`post_id`) REFERENCES `blogsite_post` (`id`);
COMMIT;
Exécutons maintenant les migrations pour qu’elles soient appliquées à notre base de données MySQL.
python manage.py migrate
Nous verrons la sortie suivante:
OutputOperations to perform:
Apply all migrations: admin, auth, blogsite, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying blogsite.0001_initial... OK
Applying sessions.0001_initial... OK
Vous avez maintenant appliqué vos migrations avec succès.
Il est important de garder à l'esprit qu'il existe trois réserves aux migrations Django avec MySQL comme moteur de base, comme indiqué dans la documentation de Django.
-
Absence de prise en charge des transactions relatives aux opérations de modification de schéma. En d’autres termes, si une migration ne s’applique pas correctement, vous devrez désélectionner manuellement les modifications que vous avez apportées afin de tenter une autre migration. Il est impossible de revenir en arrière à une étape antérieure avant que des modifications aient été apportées à la migration ayant échoué.
-
Pour la plupart des opérations de modification de schéma, MySQL réécrit entièrement les tables. Dans le pire des cas, la complexité temporelle doit être proportionnelle au nombre de lignes du tableau pour ajouter ou supprimer des colonnes. Selon la documentation de Django, cela pourrait être aussi lent qu'une minute par million de lignes.
-
Dans MySQL, la longueur des noms pour les colonnes, les tables et les index est limitée. La taille combinée de toutes les colonnes et couvertures d'index est également limitée. Bien que d'autres serveurs puissent prendre en charge des limites plus élevées créées dans Django, les mêmes index ne seront pas créés avec un serveur MySQL en place.
Pour chaque base de données que vous envisagez d'utiliser avec Django, veillez à peser les avantages et les inconvénients de chacune.
[[step-5 -—- verify-database-schema]] == Étape 5 - Vérifier le schéma de la base de données
Une fois les migrations terminées, nous devrions vérifier la génération des tables MySQL que nous avons créées via nos modèles Django.
Pour ce faire, exécutez la commande suivante dans le terminal pour vous connecter à MySQL.
mysql blog_data -u root
Maintenant, montrez les bases de données existantes.
SHOW DATABASES;
Sélectionnez notre base de donnéesblog_data
:
USE blog_data;
Ensuite, tapez la commande suivante pour afficher les tables.
SHOW TABLES;
Vous devriez voir ce qui suit:
Output+----------------------------+
| Tables_in_blog_data |
+----------------------------+
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| blogsite_comment |
| blogsite_post |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+----------------------------+
Vous verrezblogsite_comment
etblogsite_post
. Ce sont les modèles que nous avons fabriqués nous-mêmes. Vérifions qu’ils contiennent les champs que nous avons définis.
DESCRIBE blogsite_comment;
Output+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(42) | NO | | NULL | |
| email | varchar(75) | NO | | NULL | |
| website | varchar(200) | YES | | NULL | |
| content | longtext | NO | | NULL | |
| created_on | datetime(6) | NO | | NULL | |
| post_id | int(11) | NO | MUL | NULL | |
+------------+--------------+------+-----+---------+----------------+
7 rows in set (0.01 sec)
DESCRIBE blogsite_post;
Output+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| title | varchar(255) | NO | | NULL | |
| slug | varchar(255) | NO | UNI | NULL | |
| content | longtext | NO | | NULL | |
| created_on | datetime(6) | NO | | NULL | |
| author | longtext | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
6 rows in set (0.01 sec)
Nous avons vérifié que les tables de base de données avaient été générées avec succès à partir de nos migrations de modèles Django.
Vous pouvez fermer MySQL avecCTRL
+D
et lorsque vous êtes prêt à quitter votre environnement Python, vous pouvez exécuter la commandedeactivate
:
deactivate
La désactivation de votre environnement de programmation vous ramènera à l'invite de commande du terminal.
Conclusion
Dans ce didacticiel, nous avons ajouté des modèles de fonctionnalités de base pour une application Web de blog. Vous avez appris comment codermodels
, comment fonctionnemigrations
et le processus de conversion de Djangomodels
en tables de base de donnéesMySQL
réelles.