Django 6.0 en 2026 : clés primaires composites, tâches en arrière-plan et questions d'entretien
Django 6.0 en 2026 : clés primaires composites, tâches en arrière-plan natives, template partials, middleware CSP et questions d'entretien technique.

Django 6.0 marque un tournant dans la maturité du framework en 2026. Cette version majeure apporte des fonctionnalités attendues depuis des années par la communauté Python : les clés primaires composites natives dans l'ORM, un système intégré de tâches en arrière-plan, les template partials pour les composants réutilisables et un middleware Content Security Policy directement dans le noyau. Chacune de ces évolutions réduit la dépendance aux paquets tiers et simplifie l'architecture des applications Django en production.
Django suit un cycle de release prévisible avec une version majeure tous les 8 mois environ. Django 5.2 LTS (avril 2025) a introduit les clés primaires composites en version stable. Django 6.0 (décembre 2025) les intègre pleinement au reste de l'ORM tout en ajoutant le système de tâches, les template partials et le middleware CSP. Python 3.12 ou supérieur est requis.
Clés primaires composites avec CompositePrimaryKey
Les bases de données relationnelles utilisent les clés primaires composites pour identifier un enregistrement de manière unique à partir de la combinaison de deux colonnes ou plus. Jusqu'à Django 5.2, modéliser cette relation nécessitait des solutions de contournement comme unique_together ou des paquets tiers. CompositePrimaryKey résout ce problème directement dans l'ORM.
Le cas d'usage le plus courant concerne une table intermédiaire où la combinaison de deux clés étrangères constitue l'identité unique de l'enregistrement. L'exemple suivant modélise un inventaire où chaque produit dans chaque entrepôt possède une quantité associée :
# models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=100)
sku = models.CharField(max_length=20, unique=True)
class Warehouse(models.Model):
code = models.CharField(max_length=10, primary_key=True)
location = models.CharField(max_length=200)
class Inventory(models.Model):
pk = models.CompositePrimaryKey("product_id", "warehouse_id")
product = models.ForeignKey(Product, on_delete=models.CASCADE)
warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField(default=0)
last_restocked = models.DateTimeField(auto_now=True)Le champ pk reçoit les noms des colonnes sous-jacentes (et non les noms des champs du modèle). Django génère une contrainte PRIMARY KEY (product_id, warehouse_id) au niveau de la base de données, garantissant l'unicité sans nécessité d'un champ id auto-incrémenté.
Interroger les clés composites dans l'ORM
L'interaction avec l'ORM conserve l'interface habituelle. La clé composite est représentée sous forme de tuple Python, ce qui permet de filtrer, créer et assigner des enregistrements de manière directe :
# views.py
from .models import Inventory, Product, Warehouse
# Create records
laptop = Product.objects.create(name="Laptop Pro", sku="LP-001")
warehouse_a = Warehouse.objects.create(code="WH-A", location="Berlin")
item = Inventory.objects.create(
product=laptop,
warehouse=warehouse_a,
quantity=50
)
# Access the composite pk as a tuple
print(item.pk) # (1, "WH-A")
# Filter by composite pk
result = Inventory.objects.filter(pk=(1, "WH-A")).first()
# Assign a composite pk directly
new_item = Inventory(pk=(2, "WH-B"))
print(new_item.product_id) # 2
print(new_item.warehouse_id) # "WH-B"Cette fonctionnalité s'avère particulièrement précieuse pour les équipes travaillant avec des schémas de base de données existants ou migrant depuis d'autres ORM qui supportaient déjà les clés composites. Django Admin, les sérialiseurs de DRF et le système de migrations reconnaissent automatiquement les modèles utilisant CompositePrimaryKey.
Tâches en arrière-plan natives avec le décorateur @task
Django 6.0 intègre un système de tâches en arrière-plan directement dans le framework. Le module django.tasks expose un décorateur @task et une méthode .enqueue() permettant de différer l'exécution de fonctions sans configurer de broker de messages externe ni de worker indépendant.
Ce système cible les opérations courantes qui ne doivent pas bloquer le cycle requête-réponse HTTP : envoi de courriels, génération de rapports, traitement de fichiers et appels à des API externes. La définition des tâches suit la convention Django classique d'un module tasks.py dans chaque application :
# tasks.py
from django.tasks import task
from django.core.mail import send_mail
@task
def send_welcome_email(user_email, username):
"""Send a welcome email after user registration."""
send_mail(
subject="Welcome to the platform",
message=f"Hello {username}, your account is ready.",
from_email=None, # uses DEFAULT_FROM_EMAIL
recipient_list=[user_email],
)
return f"Email sent to {user_email}"
@task
def generate_report(report_id, format="pdf"):
"""Generate an export report asynchronously."""
from .services import ReportService
report = ReportService.generate(report_id, format=format)
return report.file_pathLe dispatch depuis une vue s'effectue via la méthode .enqueue(), qui sérialise les arguments et les transmet au backend configuré pour une exécution asynchrone :
# views.py
from .tasks import send_welcome_email, generate_report
def register_user(request):
# ... user creation logic ...
# Enqueue the task for background execution
send_welcome_email.enqueue(
user_email=user.email,
username=user.username
)
return redirect("dashboard")
def export_view(request, report_id):
generate_report.enqueue(report_id=report_id, format="csv")
return JsonResponse({"status": "processing"})Django 6.0 fournit un backend base de données par défaut ainsi qu'un backend Redis pour les scénarios à volume plus élevé. La configuration dans settings.py permet de sélectionner le backend et d'ajuster les paramètres tels que le nombre de workers et l'intervalle de polling.
Il convient de distinguer clairement le périmètre de ce système. Les tâches natives de Django 6.0 couvrent les cas d'usage simples à modérés de manière efficace. Pour les scénarios nécessitant un routage avancé de files, des workflows complexes (chains, chords), des politiques de relance avec backoff exponentiel configurable ou un traitement distribué sur plusieurs machines, Celery reste l'outil adapté.
Template partials : composants réutilisables dans le moteur de templates
Le moteur de templates de Django gagne une fonctionnalité que les développeurs de frameworks frontend considèrent comme acquise : la possibilité de définir des fragments réutilisables au sein d'un même fichier et de les référencer de manière sélective. Les balises {% partialdef %} et {% partial %} permettent de regrouper plusieurs composants visuels dans un seul template et de ne consommer que le fragment nécessaire.
L'exemple suivant définit deux représentations d'un produit -- une carte pour les vues catalogue et une ligne pour les tableaux d'inventaire -- dans le même fichier de templates :
<!-- templates/components/cards.html -->
{% partialdef product_card %}
<div class="card">
<h3>{{ product.name }}</h3>
<p class="price">{{ product.price|floatformat:2 }} EUR</p>
<span class="stock {% if product.in_stock %}available{% else %}sold-out{% endif %}">
{% if product.in_stock %}In Stock{% else %}Sold Out{% endif %}
</span>
</div>
{% endpartialdef %}
{% partialdef product_row %}
<tr>
<td>{{ product.name }}</td>
<td>{{ product.price|floatformat:2 }} EUR</td>
<td>{{ product.quantity }}</td>
</tr>
{% endpartialdef %}L'inclusion sélective d'un partial s'effectue via la syntaxe de fragment #nom dans la balise {% include %} :
<!-- templates/shop/catalog.html -->
{% extends "base.html" %}
{% block content %}
<div class="product-grid">
{% for product in products %}
{% include "components/cards.html#product_card" %}
{% endfor %}
</div>
{% endblock %}L'avantage principal réside dans la réduction de la prolifération de fichiers. Avant les template partials, chaque variation visuelle d'un composant nécessitait son propre fichier. Désormais, les variations apparentées coexistent dans un même fichier, ce qui facilite la maintenance et la navigation dans le code. Cette fonctionnalité s'intègre naturellement avec HTMX et d'autres patterns d'échange partiel de HTML, où le serveur doit renvoyer des fragments spécifiques d'une page sans effectuer le rendu complet du template.
Prêt à réussir tes entretiens Django ?
Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.
Middleware CSP natif pour Content Security Policy
La protection contre les attaques de cross-site scripting (XSS) et d'injection de contenu requiert des en-têtes Content Security Policy correctement configurées. Django 6.0 intègre un middleware dédié et un module django.utils.csp qui éliminent la nécessité de paquets externes comme django-csp.
La configuration se définit dans settings.py via un dictionnaire qui associe les directives CSP à leurs valeurs autorisées :
# settings.py
from django.utils.csp import CSP
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.middleware.security.ContentSecurityPolicyMiddleware",
# ... other middleware
]
SECURE_CSP = {
"default-src": [CSP.SELF],
"script-src": [CSP.SELF, CSP.NONCE],
"style-src": [CSP.SELF, "https://fonts.googleapis.com"],
"img-src": [CSP.SELF, "https:", "data:"],
"font-src": [CSP.SELF, "https://fonts.gstatic.com"],
"connect-src": [CSP.SELF],
}
# Report-only mode for testing (does not block, only reports violations)
SECURE_CSP_REPORT_ONLY = {
"default-src": [CSP.SELF],
"report-uri": ["/csp-report/"],
}La constante CSP.NONCE génère automatiquement un nonce unique par requête et l'injecte dans les balises <script> du template. Cela permet d'exécuter les scripts inline légitimes tout en bloquant tout script injecté par un attaquant. Le mode SECURE_CSP_REPORT_ONLY s'avère particulièrement utile lors de la phase de déploiement : les violations sont enregistrées sans bloquer les ressources, ce qui permet d'affiner progressivement les politiques avant d'activer le mode de blocage effectif.
L'intégration native garantit la compatibilité avec le moteur de templates Django, y compris la génération automatique d'attributs nonce dans les blocs {% static %} et dans les scripts inline du panneau d'administration.
Autres changements notables dans Django 6.0
Au-delà des fonctionnalités phares, Django 6.0 apporte des améliorations qui impactent l'expérience de développement au quotidien.
BigAutoField comme champ par défaut : DEFAULT_AUTO_FIELD pointe désormais vers BigAutoField dans les nouveaux projets, supprimant la limite de 2,1 milliards d'enregistrements qu'imposait AutoField. Les projets existants n'ayant pas configuré cette valeur explicitement recevront un avertissement lors des migrations.
Pagination asynchrone : les QuerySet paginés supportent désormais des méthodes asynchrones comme await page.ahas_next() et await page.ahas_previous(). Les vues asynchrones peuvent ainsi paginer les résultats sans bloquer la boucle d'événements, améliorant le débit des applications ASGI.
Auto-imports dans le shell : la commande python manage.py shell importe automatiquement tous les modèles du projet ainsi que les modules les plus utilisés (django.db.models, django.utils.timezone, datetime). Cette amélioration supprime l'écriture répétitive des imports à chaque ouverture de session interactive de débogage.
API de messagerie modernisée : le module django.core.mail intègre le support natif des pièces jointes inline, des en-têtes personnalisés et une interface fluide qui simplifie la composition de courriels complexes sans manipulation directe des objets MIME.
Questions d'entretien sur Django 6.0 en 2026
Les entretiens techniques pour les postes backend Python en 2026 intègrent progressivement des questions sur les fonctionnalités de Django 6.0. Les questions suivantes couvrent les sujets les plus susceptibles d'apparaître lors d'un processus de recrutement Django.
Q : Quelle différence entre unique_together et CompositePrimaryKey ?
unique_together crée une contrainte d'unicité sur un ensemble de colonnes, mais le modèle conserve son champ id auto-incrémenté comme clé primaire. CompositePrimaryKey supprime le champ id et établit la combinaison de colonnes comme véritable clé primaire au niveau de la base de données. La première constitue une contrainte supplémentaire ; la seconde redéfinit l'identité même de l'enregistrement.
Q : Quand privilégier les tâches natives de Django 6.0 plutôt que Celery ?
Le système natif convient aux tâches simples ne nécessitant ni routage de files, ni mécanismes de relance sophistiqués, ni workflows de type canvas (chains, groups, chords). Celery s'impose lorsque l'application requiert un traitement distribué sur plusieurs machines, une planification périodique avancée (Celery Beat) ou une surveillance en temps réel avec des outils comme Flower.
Q : Comment la clé primaire composite est-elle accessible dans l'ORM ?
La propriété pk d'une instance utilisant CompositePrimaryKey retourne un tuple Python contenant les valeurs des colonnes composant la clé. Le filtrage s'effectue avec Model.objects.filter(pk=(valeur1, valeur2)) et l'assignation avec instance = Model(pk=(valeur1, valeur2)). L'ORM décompacte automatiquement le tuple dans les champs correspondants.
Q : Quel avantage les template partials offrent-ils par rapport aux fichiers d'include multiples ?
Les template partials permettent de définir plusieurs fragments réutilisables dans un seul fichier, réduisant la prolifération de petits fichiers et facilitant la navigation dans le code. La syntaxe {% include "fichier.html#nom" %} référence sélectivement un fragment, ce qui s'intègre de surcroît avec les patterns d'échange partiel de HTML comme HTMX.
Conclusion
- Clés primaires composites suppriment la nécessité de champs
idartificiels dans les tables intermédiaires et de relation, alignant l'ORM Django sur le modèle relationnel standard des bases de données - Tâches natives en arrière-plan réduisent la complexité opérationnelle pour les opérations asynchrones simples en éliminant la dépendance à un broker et à des workers externes
- Template partials organisent les fragments réutilisables au sein d'un même fichier, réduisant la prolifération de templates et facilitant l'intégration avec les patterns d'échange partiel comme HTMX
- Middleware CSP natif fournit une protection contre les attaques XSS avec génération automatique de nonces et mode report-only pour les déploiements progressifs
- BigAutoField par défaut prévient l'épuisement des clés primaires dans les tables à fort volume sans configuration supplémentaire
- Pagination asynchrone et auto-imports dans le shell améliorent la productivité quotidienne du développeur aussi bien dans le code de production que dans les sessions de débogage
- Django 6.0 nécessite Python 3.12+ et reste compatible avec les principales bases de données supportées (PostgreSQL, MySQL, SQLite, Oracle)
Passe à la pratique !
Teste tes connaissances avec nos simulateurs d'entretien et tests techniques.
Tags
Partager
Articles similaires

Django et Celery : traitement asynchrone des tâches et questions d'entretien 2026
Guide Django Celery avec exemples pratiques, routage de tâches, planification Beat, configuration production et questions d'entretien technique 2026.

Django 5.2 : Middleware Personnalisé et Gestion des Signaux pour les Entretiens Techniques
Guide complet sur les middleware personnalisés et les signaux dans Django 5.2. Exemples pratiques de middleware de logging, middleware asynchrone, signaux pre_save/post_save et questions fréquentes en entretien.

Django ORM : Optimiser vos requêtes pour des performances maximales
Guide complet pour optimiser les requêtes Django ORM. select_related, prefetch_related, index, analyse N+1 et techniques avancées pour des applications performantes.