2008-12-09 8 views
4

J'ai un sur un formulaire tenant des marques de voiture. Je veux filtrer ma base de données de voitures sur les marques qui ont été vérifiées mais cela cause un problème. Comment obtenir toutes les instructions Q(make=...) dynamiquement?Django dynamic OU requêtes

Comment je commence: ['value1', 'value2', ...]

Comment je veux mettre fin: Q(col='value1') | Q(col='value2') | ...

J'ai deux autres méthodes. J'ai essayé d'ajouter des querysets pour chaque marque et de le faire dans l'autre sens (faire plusieurs exclut) mais ils étaient tous les deux très lents.

Répondre

6

Avez-vous essayé: Model.objects.filter(make__in=list_of_makes)?

Le list_of_makes est ce qui est renvoyé par le MultipleChoiceField

Voir the query set reference sur l'opérateur __in.

+0

C'est de la magie sorcière! – Oli

4

Il y avait une autre méthode prévue à l'#django:

reduce(lambda x,y: x | y, [Q1, Q2, Q3, ...]) 

Ber's method est grand pour cette instance, mais si vous avez besoin de filtrer sur des colonnes dynamiques, la cartographie ressemble à la prochaine manière la plus propre.

+0

Vous pouvez utiliser l'opérateur __in ici aussi, si vous construisez dynamiquement les arguments: requête = { '% s__in' % col_name: list_of_values} Model.objects.filter (**) requête utilisant l'expansion arg mot-clé – Ber

+0

I pense, cette carte dans ce cas devrait être remplacé par réduire. – xaralis

3

J'ai essayé la réponse de Oli, mais cela n'a pas fonctionné, même avec réduire() car il semble objets Q n'acceptent pas les dictionnaires comme argument:

Voici comment je l'avais travail:

# These are the fields I want to search with an OR clause 
search_fields = ['title__icontains', 'publisher__name__icontains', 'authors__name__icontains'] 

search = 'search string' 
clauses = [] 
for item in search_fields: 
    clauses.append(queryset.filter(**{item: search})) 
    queryset = reduce(lambda x, y: x | y, clauses).distinct() 

Vérifiez les problèmes de performances car je n'ai pu tester qu'avec un petit jeu de données.