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
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 champ | Types de base de données correspondants | Cas d'utilisation |
|---|---|---|
| CharField(max_length=N) | VARCHAR(N) | Texte court pour les titres, les étiquettes, les noms, etc. |
| TextField() | TEXT | Corps de l'article, introduction, commentaires et autres contenus |
| IntegerField() | INTEGER | Nombres entiers pour les comptages, les âges, etc. |
| DateTimeField() | DATETIME | Date et heure de publication, date et heure de mise à jour |
| ForeignKey() | Contrainte de clé étrangère | Relation un-à-plusieurs (article → catégorie) |
| ManyToManyField() | table de jointure | Relation plusieurs-à-plusieurs (article ←→ étiquette) |
| SlugField() | VARCHAR | Identifiant 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écuter
makemigrations+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
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éthodes | SQL équivalent | Valeur de retour |
|---|---|---|
Post.objects.all() | SELECT * FROM blog_post | QuerySet (tous les articles) |
Post.objects.get(id=1) | SELECT ... WHERE id=1 | Objet 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 DESC | QuerySet |
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