Michael Halim
Michael Halim

Reputation: 726

How to construct dynamic Q() in Django

I'm trying to filter dynamic value from a form in template to my query in Django project

the value can be dynamic, but it would look like this

first_query = ['a', 'b', 'c']
second_query = ['d', 'e', 'f']

what i want to achieve is to query something like this

SELECT * FROM table WHERE column_1 = 'a' OR column_1 = 'b' OR column_1 = 'c' OR column_2 = 'd' OR column_2 = 'e' OR column_2 = 'f'

Here's what i've done

        first_query = [ Q(column_1__contains=w) for w in first_query ]

        """
        If you print first_query
        [<Q: (AND: ('column_1__contains', 'a'))>, <Q: (AND: ('column_1__contains', 'b'))>, 
          <Q: (AND: ('column_1__contains', 'c'))>]
        """


        reduce_first_query = reduce(or_, query_first_query)
        """
        (OR: ('column_1', 'a'), ('column_1', 'b'),('column_1', 'c'))
        """
        

        second_query = [ Q(column_2__contains=w) for w in second_query ]
        reduce_second_query = reduce(or_, query_second_query)

When i try to filter Item from my database it gives me rows more than doubled than what i do directly from the database

test_item = Item.objects.filter(reduce_first_query) # Gives 1900 ish rows, should be 900 ish

What do i do wrong, is it because of the way i construct Q() ? or there other mistake ?

NOTES

Upvotes: 0

Views: 42

Answers (1)

Eugene Prikazchikov
Eugene Prikazchikov

Reputation: 1904

To produce the query that you specified, you need in lookup, not contains:

first_query = ['a', 'b', 'c']
second_query = ['d', 'e', 'f']

qs = Item.objects.filter(Q(column1__in=first_query) | Q(columns2__in=second_query))

And btw, you can inspect the SQL query produced by ORM like this:

print(qs.query)

Upvotes: 1

Related Questions