I have a query method with several optional filters. I want if I pass some not None value to filter parameters then do a filter, if filter value is None to 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()
I want to avoid the pattern:
if XXX:
res.filter(XXX=XXX)
Is there a more elegant way? For example, pass various filters as parameters. Or maybe 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.