Suppose I have a query method with serveral optional filters. What I want to achieve is, If I pass some not None value to filter parameters then do a filter, if filter value is None, then just ignore it.
def get_query_results(filter1=None, filter2=None, ...):
res = models.Item.query
if filter1 is not None:
res = res.filter(filter1=filter1)
if filter2 is not None:
res = res.filter(filter2=filter2)
....
return res.all()
What I want to avoid is the pattern
if XXX:
res.filter(XXX=XXX)
I wonder if there is any more elegant way to achieve this?
For example, pass various filters as parameters?
Or maybe, we can do some magic to omit the filter when the filter value is None?
Code perfectly equivalent to the one you've shown is:
def get_query_results(*filters):
res = models.Item.query
for i, filt in enumerate(filters, 1):
if filt is not None:
d = {'filter{}'.format(i): filt}
res = res.filter(**d)
return res.all()
I'm not quite sure why you need the named argument to res.filter
to be specifically filter1
, filter2
, etc, but this snippet will do it without the repetitious pattern that you understandably want to avoid.
Should the names not actually be filter1
, filter2
, etc, that's OK as long as the required names are known:
NAMES = 'foo bar baz bat'.split()
def get_query_results(*filters):
res = models.Item.query
for name, filt in zip(NAMES, filters):
if filt is not None:
d = {name: filt}
res = res.filter(**d)
return res.all()
This variant would work in this case.