Introduction
Lorsque l’on développe des applications web avec Django, il est fréquent de devoir filtrer des enregistrements dans la base de données à partir d’une liste de valeurs : catégories, tags, identifiants issus d’un formulaire ou paramètres de requête. Heureusement, l’ORM de Django facilite cela grâce au lookup __in.
Voyons comment utiliser cette fonctionnalité efficacement dans vos vues.
Cas d’Utilisation : Filtrer sur Plusieurs Valeurs
Supposons que vous souhaitiez récupérer tous les articles de blog appartenant à certaines catégories comme "tech", "science" ou "education". Plutôt que de chaîner plusieurs filtres, Django propose une solution bien plus propre grâce au lookup __in :
1 | q = Post.objects.filter(category__in=['tech', 'science', 'education']) |
Django traduit automatiquement cela en une clause SQL IN, efficace et évolutive.
Cette approche est logiquement équivalente à :
1 2 3 4 | q1 = Post.objects.filter(category='tech') q2 = Post.objects.filter(category='science') q3 = Post.objects.filter(category='education') q = q1 | q2 | q3 |
Les deux méthodes renverront tous les objets Post dont le champ category correspond à l’une des valeurs spécifiées. Cependant, même si elles produisent le même résultat, elles diffèrent significativement en termes de performance, lisibilité et efficacité :
| Critère | Lookup __in |
Filtres chaînés avec |
|---|---|---|
| ✅ Performance | Traduit en une seule clause SQL IN (très rapide) |
Exécute plusieurs requêtes et les fusionne en Python |
| ✅ Lisibilité | Compact, clair, sur une ligne | Plus verbeux et difficile à maintenir |
| ✅ Simplicité | Une seule requête | Plusieurs lignes et objets queryset |
| ❌ Flexibilité | Idéal pour des correspondances simples | Permet une logique personnalisée pour chaque condition |
Conclusion :
Pour les filtres simples basés sur une liste de valeurs, utilisez __in — c’est la solution optimisée et recommandée dans l’univers Django. Les filtres chaînés ne sont utiles que si vous avez besoin d’une logique conditionnelle par cas.
Exemple : Utiliser __in dans une Vue Django
Voici un exemple concret d’utilisation dans une vue :
1 2 3 4 5 6 7 | from django.shortcuts import render from .models import Product def featured_products(request): featured_categories = ['electronics', 'books', 'home'] products = Product.objects.filter(category__in=featured_categories) return render(request, 'products/featured.html', {'products': products}) |
Cela renvoie tous les produits dont la catégorie est "electronics", "books" ou "home".
Filtrage Dynamique avec les Paramètres GET
Vous pouvez également rendre vos filtres dynamiques en utilisant les paramètres GET de l’URL :
1 2 3 4 | def filter_by_ids(request): selected_ids = request.GET.getlist('id') # ex : ?id=1&id=2&id=3 users = User.objects.filter(id__in=selected_ids) return render(request, 'users/list.html', {'users': users}) |
C’est très utile lorsqu’on utilise un champ multi-sélection côté frontend.
Astuce : Combiner avec d’Autres Filtres
Vous pouvez combiner __in avec d’autres filtres sans problème :
1 | Event.objects.filter(status='active', location__in=['NY', 'CA']) |
Cela sélectionne uniquement les événements actifs situés à New York ou en Californie.
À Ne Pas Confondre : in en Python Est Différent
Parfois, vous souhaitez simplement vérifier si une valeur se trouve dans une liste Python, sans requête à la base :
1 2 | if user_role in ['admin', 'editor']: allow_access = True |
Ce test se fait côté Python, pas dans la base de données.
Résumé
- Utilisez
field__in=[...]pour filtrer des modèles Django à partir d’une liste. - Combinez avec les paramètres GET pour un filtrage dynamique.
- Utilisez le
innatif de Python pour les tests hors base de données.
Références
| Liens | Site |
|---|---|
__in |
docs.djangoproject.com |
Utiliser __in avec insensibilité à la casse |
forum.djangoproject.com |
