2 votes

Comment créer un filtre à partir des paramètres de request.GET ?

Duplicata possible :
filtre utilisant l'objet Q avec dynamique de l'utilisateur ?

Je travaille sur une fonction de filtre dans mon application. J'envoie une chaîne de caractères séparée par des virgules à Django via jquery (dans jquery, je remplace l'espace par un +, pour qu'elle puisse être envoyée par câble).

/?ajax&sales_item=t2,+t1

Maintenant, dans la vue, lorsque je récupère les paramètres GET, je peux voir que Django a déjà remplacé le + par un espace, ce qui est génial. Ensuite, je sépare les mots-clés par une virgule et je supprime les espaces.

sales_item_raw = request.GET['sales_item']
sales_item_keywords = sales_item_raw.split(',')            

Je dois d'abord vérifier si les noms donnés existent en tant qu'articles de vente. Je dois utiliser un icontains et donc sales_items peuvent être plus d'un élément.

for item in sales_item_keywords:
        sales_items = profile.company.salesitem_set.filter(item_description__icontains=item.strip())            

Enfin, le queryset est utilisé pour filtrer les offres pour les sales_items donnés :

deals_queryset = deals_queryset.filter(sales_item__in=sales_items)

Si l'utilisateur ne filtre qu'un seul mot-clé, cela fonctionne bien, mais s'il y a deux mots-clés, le système de gestion de l'information de l'entreprise ne fonctionne pas. sales_items sera évidemment écrasé à chaque itération de la boucle.

Quelle est la manière la plus performante de résoudre ce problème ? Dois-je simplement ajouter le contenu de sales_items à chaque itération vers une liste en dehors de la boucle ? Et finalement envoyer la nouvelle liste à la dernière deals_queryset.filter ?

Je ne suis pas sûr que ce soit une bonne façon de résoudre le problème...

0voto

Ghopper21 Points 2709

Utilisez la fonction Q pour créer une logique "ou" dans votre filtre.

# create a chain of Qs, one for each item, and "or" them together 
q_filters = Q(item_description__icontains=sales_item_keywords[0].strip())
for item in sales_item_keywords[1:]:
    q_filters = q_filters | Q(item_description__icontains=item.strip())   

# do a single filter with the chained Qs
profile.company.salesitem_set.filter(q_filters)

C'est un code moche, car je ne sais pas comment gérer le Q initial de manière élégante, car je ne sais pas ce qu'est un Q "vide" auquel on peut enchaîner tous les autres Q, y compris le premier. (Je suppose que vous pourriez utiliser Q(pk=pk) mais c'est laid d'une manière différente).

EDIT : Le lien d'Ignacio ci-dessus indique la marche à suivre, à savoir

q_filters = reduce(operator.or_, (Q(item_description__icontains=item.strip()) for item in sales_items_keywords))
profile.company.salesitem_set.filter(q_filters)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X