megapihar753
megapihar753

Reputation: 33

Django filtering from models: Model.objects.filter(Q())

I need to search for some data in the database using django ORM and this should be searching by all columns. The problem is that I do not know what to search before I get into the function as a parameter.

This is the source code:

search = request.GET.get('search_value')
#row_to_search is turple i get to function
#it could be different at every searching
#it looks like here:
rows_to_search = ('name', 'age', 'salary')

I need to search in my database for that rows, something like this:

query = Mymodel.objects.filter(Q(name__iregex=search) |      \
                               Q(age__iregex=search)  |      \
                               Q(salary__iregex=search))

How do I make the code if I will get more rows to search for?

I tried something like this but it seams it is not working at all:

Q_filter = map(lambda q: 'Q('+q+')', map(lambda s: s+'__regex='+search, rows_to_search))
searchline = '|'.join(Q_filter)

I can not call model.objects.filter(searchline), because it is an String. Is it possible to do something here, or it is the architecture wrong? Should I make a custom model manager?

Upvotes: 3

Views: 1577

Answers (1)

Ozgur Vatansever
Ozgur Vatansever

Reputation: 52173

Here is one way to do it explicitly:

>>> Q_filter = Q()
>>> for value in rows_to_search:
...     Q_filter |= Q(**{"{}__iregex".format(value): search})

Here is one-liner using reduce():

>>> Q_filter = reduce(lambda x, y: x | Q(**{"{}__iregex".format(y): search}), rows_to_search, Q())

Another one-liner using operator.or_ with list comprehensions:

>>> Q_filter = reduce(operator.or_, [Q(**{"{}__iregex".format(key): search}) for key in rows_to_search])

Then you can call the query as follows:

MyModel.objects.filter(Q_filter)

Upvotes: 3

Related Questions