Atul Bhatia
Atul Bhatia

Reputation: 1795

dynamic search with django form

Using django, I want to dynamically search for text across multiple fields. I have a list of fields to search across as well as the text to search against. I also have an initial queryset to query against. Something along these lines:

def dynamic_search(queryset):
    search_fields = ["search_field1", "search_field2", "search_field3"]
    search_text = "dummy_text"

    # I want to dynamically generate this query
    qs.filter(Q(search_field1__contains=search_text) | Q(search_field2__contains=search_text) | Q(search_field3__contains=search_text))

The issue is that search_fields is a generic list so I need to dynamically query against those fields as well. Is there a good way to do this in django?

Upvotes: 0

Views: 1128

Answers (2)

NDevox
NDevox

Reputation: 4086

Not sure about a Django specific one, but you could use eval.

N.B: THIS IS A BAD IDEA IF YOU ARE USING USER INPUT AND COULD OPEN UP ALL SORTS OF INSECURITIES. - but if you are in complete control of it it should be fine.

x = []
for search_field in search_fields:
    x.append(eval("qs.filter(Q({}__contains={})".format(search_field, search_text))

I'm storing in a list just for convenience. If you are allowed to use the | operator in your Django query - I don't know i you can, you could just assign it to a variable.

Upvotes: 0

garnertb
garnertb

Reputation: 9594

You can use the or_ method from the operator builtins, a list comprehension and the reduce builtin like this:

from django.db.models import Q
import operator


def dynamic_search(queryset):
    search_fields = ["search_field1", "search_field2", "search_field3"]
    search_text = "dummy_text"
    queryset.filter(reduce(operator.or_, [Q(**{'{0}__contains'.format(search_field): search_text}) for search_field in search_fields]))

Upvotes: 1

Related Questions