3

Hi i'm trying to run a model search query through a dictionary data which i got like so:

{
   "city":5,
   "direction":"ne",
   ..other data that can be dynamic...
   "address__icontains" = ["word1", "word2", "word3"],
}

My search query:

 Models.objects.filter(**query_dict)

since the other data are dynamic that why i use filter with dictionary.And i'm using __icontains to search up field address(string value) that contains those 3 words in that string, so the problem right now is since __icontains doesn't accept array like so in the query set:

Models.objects.filter(other keys and values from dictionary, address__icontains= ["word1", "word2", "word3"])

How would i make this work with the dictionary filter search ?

my data in dict has 3 types string, int and list(1 for range search the other for icontains search) i would like to combine dictionary search with icontains AND search

I also tried changing the dictionary to

"address__icontains" = "word1 word2 word3"

but it also doesn't work

Example data:

what im doing is find a Property that has an address field that has dynamic data like city, street, ward and district

For example:

Đường ĐT 9(street), Xã Mỹ Hạnh Nam(ward), Đức Hòa(district), Long An(city)

and it also has other data for example like direction="ne" and specials one that search between range so has key like "size__range": [0,1000] in the dict

for example if "address__icontains" = ["Long An", "Đức Hòa", "Xã Mỹ Hạnh Nam"] then it should return the above Property item with that address, direction="ne" and size has value between 0 and 1000

Thank for reading

Linh Nguyen
  • 3,452
  • 4
  • 23
  • 67

1 Answers1

1

This should do the trick:

from operator import or_
from django.db.models import Q
from functools import reduce

instance = Model.objects.all()
def queryset_filter(instance, kwargs):
    for key, value in kwargs.items():
        if isinstance(value, list):
            instance.filter(reduce(or_, (Q(key=x) for x in value))
        else:
            instance.filter(key=value)
        return instance

You do a bit of extra iterating this way, but if your code requires more complex filtering (like using querysets from forms), then you will need to iterate in this manner anyways.

Lord Elrond
  • 13,430
  • 7
  • 40
  • 80
  • 1
    in the dict i also have 'road__range': [0, 1000] and i already use that for range search in filter so it's a list too – Linh Nguyen Oct 03 '19 at 07:41
  • i had make an edit to my post with example data, if isinstance(value, list): can't be apply since some of the data is range so it's list type value – Linh Nguyen Oct 03 '19 at 07:58