Я пытаюсь создать динамические c фильтры для таблицы, пользователь может указать имя столбца и его значение для получения отфильтрованных данных
Подключиться к БД для получения метаданных таблицы
db = create_engine(engineconn)
Session = sessionmaker(bind=db)
sess = Session()
metadata = MetaData()
queryobj = Table(tablename, metadata, schema=schemaname, autoload=True, autoload_with=db)
#Gets table object
"filtercols" - это список столбцов, к которым может применяться фильтр. "Filterparams" - значение параметров в формате (от пользователя через консоль)
filtercols = ['Description','Type','Created'] #Fields in the table
filterparams = [{'description': {'op': 'eq', 'val': 'Test Data'}}, {'type': {'op': 'eq', 'val': 'none'}}]
#get filter list
filterlist = self.getfilter(queryobj, filtercols, filterparams)
Применяя список фильтров к запросу, он работает отлично, если есть только один фильтр, т.е.
filterparams = [{'description': {'op': 'eq', 'val': 'Test Data'}}] --> it works fine.
Также он отлично работает для
filterparams = [{'description': {'op': 'eq', 'val': 'Test Data'}}, {'type': {'op': 'eq', 'val': 'Name'}}] i.e. non null value,
Но он не будет работать для 2 фильтров, один со значением NULL
filterparams = [{'description': {'op': 'eq', 'val': 'Test Data'}}, {'type': {'op': 'eq', 'val': 'none'}}].
В то же время, если есть только один фильтр со значением NULL, то он работает, т.е.
filterparams = [{'type': {'op': 'eq', 'val': 'none'}}]
Вызов методов
result = sess.query(queryobj).filter(*filterlist).all()
print(result)
def getfilter(self, tbl, cfgfiltercolumns, filterparams):
filters = []
'''print(1)
print(cfgfiltercolumns)
print(2)
print(filterparams)'''
iskeyfound = False
try:
#iterate through list of parameters given by the user
for item in filterparams:
# get the key and value which is formatted by 'getargs' method e.g. {'colname':{'op':'gr', val:'2020-06-01'}}
for key,value in item.items():
iskeyfound = False
#parameter given by the user should exists in 'FilterFields' for the given 'dataconfig' key
for i,cdfcol in enumerate(cfgfiltercolumns):
#colmatcheddict = {}
if(key.upper() == cdfcol.upper()):#
iskeyfound = True
#colmatcheddict[cdfcol] = item[key]
if tbl.columns.has_key(cdfcol):
#print('found')
opereratortype = item[key]['op']
paramval = item[key]['val']
if opereratortype == 'lt':
filters.append(tbl.columns[cdfcol] < paramval)
elif opereratortype == 'gt':
filters.append(tbl.columns[cdfcol] > paramval)
elif opereratortype == 'eq':
if(paramval.upper() == "NONE"):
filters.append(tbl.columns[cdfcol].is_(None))
#filters.append(tbl.columns[cdfcol] == None)
else:
filters.append(tbl.columns[cdfcol] == paramval)
elif opereratortype == 'noteq':
if(paramval.upper() == "NONE"):
filters.append(tbl.columns[cdfcol].isnot(None))
#filters.append(tbl.columns[cdfcol] != None)
else:
filters.append(tbl.columns[cdfcol] != paramval)
elif opereratortype == 'in':
formattedval = (paramval[1:len(paramval)-1])
inlist=[]
splitval = formattedval.split(',')
for item in splitval:
inlist.append(item)
#print(inlist)
filters.append(tbl.columns[cdfcol].in_(inlist))
elif opereratortype == 'notin':
formattedval = (paramval[1:len(paramval)-1])
inlist=[]
splitval = formattedval.split(',')
for item in splitval:
inlist.append(item)
#print(inlist)
filters.append(tbl.columns[cdfcol].notin_(inlist))
#filters.append(tbl.columns[cdfcol] in paramval)
else:
pass
#Logging
if (iskeyfound == False):
pass
#logging
except:
pass
#logging
print(filters)
return filters