Dynamically constructing filters in SQLAlchemy

后端 未结 5 947
挽巷
挽巷 2020-12-04 09:11

I am looking for a way to dynamically construct filters using SQLAlchemy. That is, given the column, the operator name and the comparing value, construct the corresponding f

5条回答
  •  鱼传尺愫
    2020-12-04 09:50

    class Place(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        search_id = db.Column(db.Integer, db.ForeignKey('search.id'), nullable=False)
    
        @classmethod
        def dinamic_filter(model_class, filter_condition):
            '''
            Return filtered queryset based on condition.
            :param query: takes query
            :param filter_condition: Its a list, ie: [(key,operator,value)]
            operator list:
                eq for ==
                lt for <
                ge for >=
                in for in_
                like for like
                value could be list or a string
            :return: queryset
            '''
            __query = db.session.query(model_class)
            for raw in filter_condition:
                try:
                    key, op, value = raw
                except ValueError:
                    raise Exception('Invalid filter: %s' % raw)
                column = getattr(model_class, key, None)
                if not column:
                    raise Exception('Invalid filter column: %s' % key)
                if op == 'in':
                    if isinstance(value, list):
                        filt = column.in_(value)
                    else:
                        filt = column.in_(value.split(','))
                else:
                    try:
                        attr = list(filter(lambda e: hasattr(column, e % op), ['%s', '%s_', '__%s__']))[0] % op
                    except IndexError:
                        raise Exception('Invalid filter operator: %s' % op)
                    if value == 'null':
                        value = None
                    filt = getattr(column, attr)(value)
                __query = __query.filter(filt)
            return __query
    

    Execute like:

    places = Place.dinamic_filter([('search_id', 'eq', 1)]).all()
    

提交回复
热议问题