Vue d'ensemble
Django 1.11, publié le 4 avril 2017, est la dernière version de la branche 1.x et la dernière à supporter Python 2. C'est une version LTS (Long Term Support) qui recevra des correctifs de sécurité jusqu'en avril 2020. Elle introduit les expressions Subquery dans l'ORM et le rendu des widgets de formulaire basé sur les templates.
Fonctionnalités principales
Expressions Subquery
Les expressions Subquery et Exists permettent d'imbriquer des requêtes directement dans les annotations ou les filtres de l'ORM. Cela évite les requêtes N+1 et permet des requêtes complexes sans SQL brut.
from django.db.models import OuterRef, Subquery, Exists
# Dernier commentaire de chaque article
dernier_commentaire = (
Commentaire.objects
.filter(article=OuterRef('pk'))
.order_by('-date_creation')
.values('texte')[:1]
)
articles = Article.objects.annotate(
dernier_commentaire=Subquery(dernier_commentaire)
)
for article in articles:
print(f"{article.titre} : {article.dernier_commentaire}")
# Filtrer les articles qui ont au moins un commentaire
a_des_commentaires = Commentaire.objects.filter(article=OuterRef('pk'))
articles_commentes = Article.objects.filter(
Exists(a_des_commentaires)
)
Widgets basés sur les templates
Le rendu des widgets de formulaire utilise désormais le moteur de templates au lieu de code Python en dur. Cela facilite la personnalisation de l'apparence des champs de formulaire en surchargeant simplement un template.
# Surcharge du template d'un widget input
# templates/django/forms/widgets/input.html
# <input
# type="{{ widget.type }}"
# name="{{ widget.name }}"
# class="form-control"
# {% if widget.value %}value="{{ widget.value }}"{% endif %}
# >
# Ou via un widget personnalisé
from django.forms import TextInput
class ChampRecherche(TextInput):
template_name = 'widgets/champ_recherche.html'
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
context['widget']['placeholder'] = 'Rechercher...'
return context
