Dynamically create queries from strings in django.
My problem: I wanted to make a searchable, sorted list of an arbitrary amount of fields to check against.
Normally, we’d use a Q object to get to the | “or” operator. Our search might look like the following:
Person.objects.filter( Q(first_name__icontains='Yuji') | Q(last_name__icontains='Tomita')
What if I don’t want to hard code the field names? I want to use dynamic field names so I can use a basic factory on multiple models very easily.
With much needed prodding in the right direction by mattmcc, I figured it out.
The key was how to use keyword arguments as strings.
Person.objects.filter(first_name__icontains='Yuji')
is equal to:
Person.objects.filter( **{'first_name__icontains':'Yuji'})
With this knowledge, and operator.or_, I could do a Q and | lookup via strings.
query_string = "Some Name" # the search string
argument_list = []
fields = ('search_field1','search_field2','search_field3')
for query in query_string.split(' '): # split search words
for field in fields:
argument_list.append( Q(**{field+'__icontains': query} )
query = MyModel.objects.filter( reduce(operator.or_, argument_list) ) # join the arguments in the list with the or operator