Фильтр данных Dynami c с использованием sqlalchemy, он работает для заданного значения, но не работает для значений NULL (None) - PullRequest
0 голосов
/ 17 июня 2020

Я пытаюсь создать динамические 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
...