Comment créer des modèles Django

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.

Related