Avancé
🧠 Fondamentaux
30 XP
0 personnes ont réussi
Formulaire de recherche avec filtres
En entreprise, les formulaires de recherche avec filtres sont partout : recherche de produits, filtrage de commandes, tri de résultats. Un formulaire Django est parfait pour ca car il valide et nettoie automatiquement les paramètres.
Un formulaire de recherche est généralement utilise avec des paramètres GET (pas POST), car l'URL de recherche doit etre partageable.
Crée un formulaire ProductSearchForm avec : - query : CharField, max 200, required=False (texte de recherche) - category : ChoiceField avec [('', 'Toutes'), ('electronics', 'Electronique'), ('clothing', 'Vetements'), ('books', 'Livres'), ('food', 'Alimentaire')], required=False - min_price : DecimalField, min_value=0, decimal_places=2, max_digits=10, required=False - max_price : DecimalField, min_value=0, decimal_places=2, max_digits=10, required=False - in_stock_only : BooleanField, required=False (filtrer les produits en stock) - sort_by : ChoiceField avec [('name', 'Nom'), ('price_asc', 'Prix croissant'), ('price_desc', 'Prix decroissant'), ('newest', 'Plus recents')], required=False
Ajoute une méthode clean qui vérifie que min_price <= max_price quand les deux sont renseignes. Leve ValidationError("Le prix minimum doit etre inferieur au prix maximum.") sinon.
Ajoute une méthode get_filters(self) qui retourne un dictionnaire des filtres actifs (seulement les champs qui ont une valeur non vide). Appelle d'abord self.is_valid().
form = ProductSearchForm(data={})
assert form.is_valid() == True
Filtres actifs
form = ProductSearchForm(data={'query': 'laptop', 'category': 'electronics'})
form.is_valid()
filters = form.get_filters()
assert filters.get('query') == 'laptop' and filters.get('category') == 'electronics'
Filtres vides exclus
form = ProductSearchForm(data={'query': 'test'})
form.is_valid()
filters = form.get_filters()
assert 'category' not in filters or filters.get('category') == ''
min_price > max_price invalide
form = ProductSearchForm(data={'min_price': '100', 'max_price': '50'})
assert form.is_valid() == False
+ 0 tests cachés
Indices (3 disponibles)
Solution officielle
import django
from django.conf import settings
if not settings.configured:
settings.configure(
DATABASES={},
INSTALLED_APPS=['django.contrib.contenttypes'],
DEFAULT_AUTO_FIELD='django.db.models.BigAutoField',
)
django.setup()
from django import forms
class ProductSearchForm(forms.Form):
CATEGORY_CHOICES = [
('', 'Toutes'),
('electronics', 'Electronique'),
('clothing', 'Vetements'),
('books', 'Livres'),
('food', 'Alimentaire'),
]
SORT_CHOICES = [
('name', 'Nom'),
('price_asc', 'Prix croissant'),
('price_desc', 'Prix decroissant'),
('newest', 'Plus recents'),
]
query = forms.CharField(max_length=200, required=False)
category = forms.ChoiceField(choices=CATEGORY_CHOICES, required=False)
min_price = forms.DecimalField(min_value=0, decimal_places=2, max_digits=10, required=False)
max_price = forms.DecimalField(min_value=0, decimal_places=2, max_digits=10, required=False)
in_stock_only = forms.BooleanField(required=False)
sort_by = forms.ChoiceField(choices=SORT_CHOICES, required=False)
def clean(self):
cleaned_data = super().clean()
min_p = cleaned_data.get('min_price')
max_p = cleaned_data.get('max_price')
if min_p is not None and max_p is not None and min_p > max_p:
raise forms.ValidationError("Le prix minimum doit etre inferieur au prix maximum.")
return cleaned_data
def get_filters(self):
if not self.is_valid():
return {}
filters = {}
for key, value in self.cleaned_data.items():
if value is not None and value != '' and value is not False:
filters[key] = value
return filters