Esc
 Naviguer  Ouvrir Esc Fermer
Aller au contenu

Django 6.0

🎯 Objectif : maîtriser Django 6.0 au point de livrer un CRUD complet (modèles, vues, admin, API REST) en quelques jours.

À l'issue de cet axe, tu sauras :

  • Comprendre l'organisation projet/apps et le settings.py
  • Définir des modèles avec relations et migrations
  • Utiliser l'admin Django pour générer une interface CRUD gratuite
  • Construire une API REST avec Django REST Framework (DRF)
  • Authentifier avec sessions ou JWT (SimpleJWT)
  • Tester avec pytest-django
PourContre
Tout fourni : ORM, migrations, admin auto, auth, templates, sessions, formulairesVerbeux, beaucoup de magie implicite
Admin auto = interface CRUD complète gratuite pour gérer les donnéesConvention « project + apps » à digérer
Mature depuis 2005, écosystème richeAsync ajouté tardivement (mature en 6.0+)
Excellent pour un CRUD complet d’app métierSur-dimensionné pour un microservice

Verdict 2026 : Django reste l’arme absolue pour des apps métier complètes où l’admin et la productivité priment. Pour une API moderne async, FastAPI est plus adapté.

Django 6.0 (sortie fin 2025, LTS) apporte :

  • Async views matures (depuis 4.1, stabilisées en 5.x, optimisées en 6.0).
  • Async ORM amélioré : await Model.objects.aget(...), async for obj in qs.
  • Améliorations de performances sur le templating et le routage.
  • Drop du support Python 3.10 ; cible Python 3.12+.
Fenêtre de terminal
# Avec uv (recommandé en 2026)
uv init taskly-django
cd taskly-django
uv add django djangorestframework
# Créer un projet
uv run django-admin startproject config .
# Lancer
uv run python manage.py migrate
uv run python manage.py runserver
# http://127.0.0.1:8000
taskly-django/
├── manage.py ← CLI Django
├── pyproject.toml
├── config/ ← « project » : settings, urls racine, ASGI/WSGI
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── asgi.py
├── apps/ ← convention : un dossier "apps" qui contient les apps
│ ├── accounts/ ← une « app » Django (module isolé)
│ │ ├── models.py
│ │ ├── views.py
│ │ ├── urls.py
│ │ ├── serializers.py ← DRF
│ │ ├── admin.py
│ │ └── migrations/
│ └── tasks/
└── tests/

Concept clé : un projet Django contient plusieurs apps. Une app est une unité réutilisable (modèles + vues + URLs + templates). Tu peux avoir 1 app pour accounts, 1 pour tasks, 1 pour billing.

apps/tasks/models.py
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
class Task(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='tasks')
title = models.CharField(max_length=200)
description = models.TextField(blank=True)
done = models.BooleanField(default=False)
due_at = models.DateTimeField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created_at']
indexes = [
models.Index(fields=['owner', '-created_at']),
]
def __str__(self) -> str:
return self.title
Fenêtre de terminal
uv run python manage.py makemigrations
uv run python manage.py migrate

Django génère automatiquement les migrations SQL à partir de tes modifs models.py. Le système est mature et gère bien les diffs.

# Filtrer
tasks = Task.objects.filter(owner=user, done=False)
# Joindre (évite N+1)
tasks = Task.objects.select_related('owner').filter(done=False)
# Many-to-many / reverse FK
tasks = Task.objects.prefetch_related('comments').all()
# Agréger
from django.db.models import Count
stats = Task.objects.aggregate(total=Count('id'))
# Async (Django 4.1+)
tasks = await Task.objects.filter(owner=user).acount()
async for task in Task.objects.filter(owner=user):
print(task.title)
apps/tasks/admin.py
from django.contrib import admin
from .models import Task
@admin.register(Task)
class TaskAdmin(admin.ModelAdmin):
list_display = ('title', 'owner', 'done', 'created_at')
list_filter = ('done', 'owner')
search_fields = ('title', 'description')
readonly_fields = ('created_at',)

Tu obtiens gratuitement une interface complète à /admin/ :

  • Liste filtrable, recherchable, paginée.
  • Formulaires de création/édition générés depuis les modèles.
  • Permissions par utilisateur/groupe.
  • Historique des modifications.

C’est ce qui rend Django imbattable quand tu as besoin d’un back-office sans coder.

DRF est l’extension de référence pour exposer une API JSON. Bien que NestJS-niveau de productivité.

Fenêtre de terminal
uv add djangorestframework djangorestframework-simplejwt
apps/tasks/serializers.py
from rest_framework import serializers
from .models import Task
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = ['id', 'title', 'description', 'done', 'due_at', 'created_at']
read_only_fields = ['id', 'created_at']
apps/tasks/views.py
from rest_framework import viewsets, permissions
from .models import Task
from .serializers import TaskSerializer
class TaskViewSet(viewsets.ModelViewSet):
serializer_class = TaskSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return Task.objects.filter(owner=self.request.user)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
apps/tasks/urls.py
from rest_framework.routers import DefaultRouter
from .views import TaskViewSet
router = DefaultRouter()
router.register(r'tasks', TaskViewSet, basename='task')
urlpatterns = router.urls

5 routes générées automatiquement : GET /tasks/, POST /tasks/, GET /tasks/:id/, PATCH /tasks/:id/, DELETE /tasks/:id/.

config/settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
}
# config/urls.py
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
urlpatterns += [
path('api/auth/login/', TokenObtainPairView.as_view()),
path('api/auth/refresh/', TokenRefreshView.as_view()),
]

Tu obtiens /api/auth/login/ qui prend { username, password } et renvoie { access, refresh } — JWT prêts à l’emploi.

Fenêtre de terminal
uv add --dev pytest pytest-django
tests/test_tasks.py
import pytest
from django.contrib.auth import get_user_model
from rest_framework.test import APIClient
User = get_user_model()
@pytest.fixture
def client():
return APIClient()
@pytest.fixture
def user(db):
return User.objects.create_user(username='alice', password='password123')
def test_list_tasks_requires_auth(client):
response = client.get('/api/tasks/')
assert response.status_code == 401
def test_create_task(client, user):
client.force_authenticate(user=user)
response = client.post('/api/tasks/', {'title': 'Test'})
assert response.status_code == 201
assert response.data['title'] == 'Test'
ComposantRecommandation
Serveur WSGIGunicorn (sync) ou Uvicorn (async via Daphne)
Reverse proxyNginx ou Caddy
Static filesWhitenoise pour les servir directement (simple)
DBPostgreSQL (le default Django)
CacheRedis
PlateformeFly.io, Render, Railway
Fenêtre de terminal
# Démarrage prod typique
uv run gunicorn config.wsgi:application --workers 4 --bind 0.0.0.0:8000
Tu construis une plateforme interne avec back-office complet (gestion utilisateurs, articles, commandes). Choix idéal en Python ?
Tu charges 100 tâches puis pour chacune tu accèdes à task.owner.email. Tu vois 101 requêtes SQL dans les logs. Pourquoi et comment fixer ?
Tu ajoutes un champ `priority` dans models.py. Que faire ensuite ?

Le projet taskly-api sera implémenté en FastAPI (notre référence). Pour faire la même chose en Django, tu peux suivre la doc DRF avec les modèles ci-dessus comme point de départ.

Suite : Flask ou FastAPI.