Refactorisation de la vue basée sur les classes (CBV)
Dans ce chapitre, vous allez apprendre les vues basées sur les classes (CBV) de Django et refactoriser la page d'accueil et la page de détail avec un code plus concis.
FBV vs CBV
Jusqu'à présent, toutes nos vues ont été écrites à l'aide de fonctions (vues basées sur les fonctions, FBV).
Django fournit égalementles vues basées sur les classes (CBV), qui utilisent des classes pour encapsuler la logique des vues.
| Fonctionnalités | FBV (vue basée sur les fonctions) | CBV (vues basées sur les classes) |
|---|---|---|
| volume de code | Flexible, mais la logique commune doit être écrite de façon répétée | Après avoir hérité de la vue générique, seules quelques lignes de code sont nécessaires |
| Lisibilité | Déroulement linéaire, logique claire | La chaîne d'héritage demande un suivi, mais une fois maîtrisée, elle est évidente au premier regard. |
| Réutilisabilité | Encapsulé via des fonctions | Utilisation de la composition de Mixin (une marque de fabrique de Django) |
| Scénarios applicables | Pages avec une logique simple et un déroulement clair | Pages récurrentes telles que créer, lire, mettre à jour, supprimer (CRUD) |
| Répartition des méthodes HTTP | Manuel : if request.method == 'POST' | Répartition automatique vers les méthodes get() / post() |
Il n'y a ni avantage ni inconvénient absolu entre les deux ; les projets Django généralement...Mélanger FBV et CBV: Utilisez FBV pour la logique complexe, et CBV pour le CRUD standard.
ListView — refactorisation de la page de liste
La vue index de la page d'accueil consiste essentiellement à :Interroger la liste des articles → rendre le template。
Pour ce genre de logique récurrente, Django...ListViewDéjà écrit pour vous.
Exemple
from django.views.generic import ListView
from django.db.models import Q
from .models import Post, Category
class PostListView(ListView):
"""Page d'accueil du blog : hérite de ListView, affiche la liste des articles"""
model = Post # Spécifier le modèle
template_name = 'blog/index.html' # Spécifier le gabarit (par défaut : blog/post_list.html)
context_object_name = 'posts' # Nom de la variable utilisée dans le gabarit (par défaut : object_list)
paginate_by = 12 # 12 éléments par page (pagination)
ordering = ['-created_at'] # Tri
def get_queryset(self):
"""Redéfinir la méthode de requête : prend en charge le filtrage par catégorie + la recherche par mot-clé"""
queryset = super().get_queryset()
# Filtre de catégorie
self.category_slug = self.request.GET.get('category', '')
if self.category_slug:
queryset = queryset.filter(category__slug=self.category_slug)
# Recherche par mot-clé
self.keyword = self.request.GET.get('q', '')
if self.keyword:
queryset = queryset.filter(
Q(title__icontains=self.keyword) |
Q(summary__icontains=self.keyword)
)
return queryset
def get_context_data(self, **kwargs):
"""Surcharger la méthode de contexte : injecter des données supplémentaires dans le template"""
context = super().get_context_data(**kwargs)
context['categories'] = Category.objects.all()
context['category_slug'] = self.category_slug
context['keyword'] = self.keyword
context['title'] = 'EXAMPLE Blog - Accueil'
return context
Comparez le volume de code avant et après refactorisation : FBV fait environ 40 lignes → CBV fait environ 30 lignes, et la logique est clairement divisée en différentes méthodes.
DetailView — refactorisation de la page de détail
Exemple
from django.views.generic import DetailView
class PostDetailView(DetailView):
"""Page de détail d'article : hérite de DetailView"""
model = Post
template_name = 'blog/post_detail.html'
context_object_name = 'post'
# pk_url_kwarg : nom du paramètre pour transmettre la clé primaire dans l'URL (par défaut, pk ; déclaré explicitement ici).
pk_url_kwarg = 'pk'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = f'{self.object.title} - Blog d'EXEMPLE'
return context
Mettre à jour la configuration des routes
La syntaxe de routage des CBV est légèrement différente de celle des FBV — elle nécessite d'appeler....as_view()。
Exemple
from django.urls import path
from django.contrib.auth import views as auth_views
from . import views
url = [
# CBV : ajoutez .as_view() après la classe pour la convertir en une fonction de vue
path('', views.PostListView.as_view(), name='index'),
path('post/<int:pk>/', views.PostDetailView.as_view(), name='post_detail'),
# Les autres vues restent inchangées
path('register/', views.register, name='register'),
path('login/', auth_views.LoginView.as_view(
template_name='blog/login.html',
redirect_authenticated_user=True
), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
path('post/<int:pk>/favorite/', views.toggle_favorite, name='toggle_favorite'),
]
Pourquoi utiliser des CBV ?
.as_view()? La configuration d'URL de Django attend un objet appelable (une fonction)..as_view()Il convertit la vue de classe en un objet appelable qui est conforme à la signature de fonction de vue de Django, et gère en interne la répartition automatique vers la méthode get() ou post() de la classe en fonction de la méthode HTTP (GET/POST).
Aperçu des vues génériques courantes
| vue | Nom du gabarit par défaut | Objectif |
|---|---|---|
| ListView | modelname_list.html | Afficher la liste des objets |
| DetailView | modelname_detail.html | Afficher les détails d'un objet unique |
| CreateView | modelname_form.html | Créer un nouvel objet (avec formulaire) |
| UpdateView | modelname_form.html | Mettre à jour un objet existant |
| DeleteView | model_name_confirm_delete.html | Confirmer la suppression de l'objet |
| TemplateView | il faut spécifier | Rendre un template statique (aucune requête de données) |
Les vues génériques de Django couvrent environ 80% des scénarios de développement web. Lorsque vous rencontrez des situations qui ne répondent pas à vos besoins, revenez aux FBV.
LoginRequiredMixin
CBV non disponible@login_requiredDécorateurs (ceux-ci sont destinés aux fonctions), passez à...LoginRequiredMixin。
Exemple
from django.views.generic import ListView
class FavoriteListView(LoginRequiredMixin, ListView):
"""Liste des favoris : connexion requise pour accéder"""
model = Post
template_name = 'blog/favorites.html'
context_object_name = 'posts'
ordering = ['-created_at']
# LoginRequiredMixin : les utilisateurs non authentifiés seront automatiquement redirigés vers settings.LOGIN_URL
def get_queryset(self):
# Afficher uniquement les articles mis en favori par l'utilisateur actuel
return self.request.user.favorite_posts.all().order_by('-created_at')
L'ordre d'héritage des Mixins est très important :
LoginRequiredMixinDoit être écrit dansListViewPlus tôt. L'ordre de résolution de l'héritage multiple de Python va de gauche à droite ; LoginRequiredMixin vérifie d'abord l'état de connexion, et ce n'est qu'après validation qu'il poursuit l'exécution de la logique de ListView.
Quand utiliser CBV, et quand utiliser FBV ?
Règle empirique :
- FBV: Vues avec une logique complexe, de nombreuses branches conditionnelles et des flux non standard (comme toggle_favorite)
- CBV: Vues avec des opérations CRUD standard et une logique pouvant être clairement scindée en get/post (comme les pages de liste, les pages de détail)
Les opérations comme toggle_favorite (bascule des favoris) ont une logique simple mais un flux différent du CRUD conventionnel ; FBV est plus approprié.
Pour les pages d'affichage de données standard comme index et post_detail, CBV peut réduire considérablement le code passe-partout.
Résumé du chapitre
Dans ce chapitre, vous avez appris l'utilisation essentielle des vues basées sur des classes de Django : ListView affiche des listes, DetailView affiche des détails, get_queryset/get_context_data personnalisent les requêtes et le contexte, as_view() active le routage, et LoginRequiredMixin remplace login_required.
Le code refactorisé de la page d'accueil et de la page de détail est plus court et a une structure plus claire.
autres extensions