Modèles et bases de données

Dans ce chapitre, vous apprendrez à utiliser Django ORM pour définir des modèles de données, créer des tables de base de données et insérer des données de test.


Pourquoi les modèles sont-ils nécessaires ?

Dans le chapitre précédent, nous avons codé en dur le texte des pages. Un vrai blog doit stocker plusieurs articles, et le contenu peut changer à tout moment.

ModèleC'est la couche de base de données de Django : utilisez des classes Python pour définir des structures de données, et Django génère automatiquement les tables de base de données correspondantes.

Vous n'avez pas besoin d'écrire une seule ligne de SQL—c'estORM (Object-Relational Mapping)la valeur fondamentale.


Définir le modèle Post

Openblog/models.py, définir le modèle d'article.

Exemple

# Chemin du fichier : blog/models.py
from django.db import models
from django.utils import timezone

class Category(models.Model):
    """Catégorie d'article"""
    name = models.CharField('nom de la catégorie', max_length=50, unique=True)
    # slug est utilisé pour les identifiants anglais dans les URL (par exemple, /category/django/)
    slug = models.SlugField('identifiant URL', max_length=50, unique=True)

    class Meta:
        verbose_name = 'Catégories'
        verbose_name_plural = 'Catégories'

    def __str__(self):
        return self.name


class Post(models.Model):
    """Article de blog"""
    # Titre : CharField est utilisé pour les textes courts ; max_length est requis.
    title = models.CharField('Titre', max_length=200)

    # slug : identifiant anglais de l'article dans l'URL
    slug = models.SlugField('identifiant URL', max_length=200, unique=True)

    # Résumé : TextField est utilisé pour les textes longs, blank=True signifie facultatif
    summary = models.TextField('Résumé', blank=True)

    # Corps : TextField sans limite de longueur
    content = models.TextField('Corps')

    # Catégorie : relation un-à-plusieurs ForeignKey, un article appartient à une catégorie
    # on_delete=models.CASCADE signifie que lorsqu'on supprime une catégorie, tous les articles qui lui sont associés sont aussi supprimés
    category = models.ForeignKey(
        Catégorie,
        on_delete=models.CASCADE,
        verbose_name='Catégories',
        related_name='posts'    # Requête inversée : category.posts.all()
    )

    # auto_now_add : remplit automatiquement l'heure actuelle lors de la création
    created_at = models.DateTimeField('Heure de création', auto_now_add=True)

    # auto_now : mis à jour automatiquement avec l'heure actuelle à chaque sauvegarde
    updated_at = models.DateTimeField('Heure de mise à jour', auto_now=True)

    class Meta:
        verbose_name = 'Articles'
        verbose_name_plural = 'Articles'
        # Trié par défaut par heure de création par ordre décroissant
        ordering = ['-created_at']

    def __str__(self):
        # Afficher le titre lors de l'affichage des objets dans l'interface d'administration et le Shell
        return self.title

Référence rapide pour les types de champs courants

Type de champTypes de base de données correspondantsCas d'utilisation
CharField(max_length=N)VARCHAR(N)Texte court pour les titres, les étiquettes, les noms, etc.
TextField()TEXTCorps de l'article, introduction, commentaires et autres contenus
IntegerField()INTEGERNombres entiers pour les comptages, les âges, etc.
DateTimeField()DATETIMEDate et heure de publication, date et heure de mise à jour
ForeignKey()Contrainte de clé étrangèreRelation un-à-plusieurs (article → catégorie)
ManyToManyField()table de jointureRelation plusieurs-à-plusieurs (article ←→ étiquette)
SlugField()VARCHARIdentifiant compatible avec les URL
ImageField()VARCHAR(path)Image de couverture, avatar (nécessite la bibliothèque Pillow)

__str__La méthode détermine comment l'objet est affiché sous forme de chaîne. Elle est appelée dans les listes déroulantes du back-office d'administration et dans la sortie du shell pour afficher le nom de l'objet. Si vous n'écrivez pas cette méthode, vous verrezPost object (1)un texte aussi dénué de sens.


Migration : synchroniser les modèles avec la base de données

Après avoir écrit les classes de modèle, vous devez utiliserMigrationpour créer les tables de la base de données.

(venv) $ python manage.py makemigrations   # 生成迁移文件(检测模型变化)
Migrations for 'blog':
  blog/migrations/0001_initial.py
    - Create model Category
    - Create model Post

(venv) $ python manage.py migrate           # 执行迁移(创建数据库表)
Operations to perform:
  Apply all migrations: admin, auth, blog, contenttypes, sessions
Running migrations:
  Applying blog.0001_initial... OK

Répartition des tâches entre les deux commandes :

  • makemigrationsAnalyse models.py et génère des scripts de migration (fichiers Python).
  • migrate: Exécute les scripts de migration pour créer les tables réelles dans la base de données.

Après chaque modification de models.py, vous devez exécutermakemigrations + migrateCes deux commandes sont toutes deux indispensables : exécuter uniquement makemigrations sans migrate signifie que les tables ne seront pas créées ; exécuter migrate directement sans makemigrations signifie que Django ne saura pas que vous avez modifié les modèles.


Utilisez le Django Shell pour insérer des données de test.

Avant de commencer à écrire des pages, utilisez d'abord Django Shell pour saisir quelques données dans la base de données afin de vérifier que le modèle fonctionne correctement.

(venv) $ python manage.py shell

Cela ouvre un Shell Python interactif où vous pouvez manipuler la base de données.

Exemple

# Saisir ligne par ligne dans le Django Shell
from blog.models import Category, Post

# 1. Créer une catégorie
cat_django = Category.objects.create(name='Django', slug='django')
cat_python = Category.objects.create(name='Python', slug='python')
cat_css = Category.objects.create(name='CSS', slug='css')

# 2. Créer un article
Post.objects.create(
    title='Le guide complet du débutant Django',
    slug='django-beginner-guide',
    summary='Apprenez Django à partir de zéro, en couvrant les concepts clés tels que les modèles, les vues, les templates, etc.',
    content='<h2>Pourquoi apprendre Django ?</h2><p>Django est l'un des frameworks web Python les plus populaires...</p>',
    category=cat_django
)

Post.objects.create(
    title='Explication détaillée de la programmation asynchrone en Python',
    slug='python-async',
    summary=Comprenez asyncio, les coroutines et les boucles d'événements en un seul article.,
    content=<h2>Qu'est-ce qu'une coroutine ?</h2><p>Une coroutine est une solution de concurrence plus légère que les threads...</p>,
    catégorie=cat_python
)

Post.objects.create(
    titre=Mise en page pratique avec CSS Grid,
    slug='css-grid-layout',
    résumé=Implémentez facilement des mises en page responsives complexes avec CSS Grid.,
    contenu=<h2>Premiers pas avec Grid</h2><p>Grid est un système de mise en page bidimensionnel...</p>,
    catégorie=cat_css
)

# 3. Vérifier les requêtes
print(Post.objects.all())           # Afficher tous les articles
print(Post.objects.count())         # Nombre total d'articles
print(Post.objects.filter(category=cat_django))  # Articles dans la catégorie Django

Requêtes de base avec Django ORM

L'ORM vous permet d'opérer sur la base de données en utilisant des chaînes de méthodes Python, sans écrire de SQL.

MéthodesSQL équivalentValeur de retour
Post.objects.all()SELECT * FROM blog_postQuerySet (tous les articles)
Post.objects.get(id=1)SELECT ... WHERE id=1Objet unique (lève une exception s'il n'est pas trouvé)
Post.objects.filter(category__slug='django')WHERE category.slug='django'QuerySet
Post.objects.order_by('-created_at')ORDER BY created_at DESCQuerySet
Post.objects.exclude(status='draft')WHERE status != 'draft'QuerySet

QuerySet estÉvaluation paresseuseC'est-à-dire : la requête n'est pas exécutée immédiatement ; le SQL n'est envoyé que lorsque les données sont réellement nécessaires (comme lors de l'itération, de l'affichage ou de la conversion en liste). Vous pouvez donc enchaîner plusieurs appels filter sans générer plusieurs requêtes.


Mise en pratique : Préparer les données pour les chapitres suivants

Dans le Shell, saisissez plusieurs autres articles et catégories, couvrant les trois catégories Django, Python et CSS, avec au moins 2 articles par catégorie.

Vous pourriez écrire une commande de gestion ou un script pour l'insertion par lots, mais à ce stade, il suffit de les insérer une par une en utilisant le Shell.


Résumé du chapitre

Dans ce chapitre, vous avez maîtrisé le flux de travail principal de l'ORM Django : définir des classes Python (modèles) dans models.py, générer des fichiers de migration avec makemigrations, synchroniser avec la base de données avec migrate, et utiliser le Shell et l'ORM pour interroger et insérer des données.

À ce stade, la structure des articles et des catégories a été établie dans la base de données.

autres extensions