Dynamically constructing filters in SQLAlchemy

后端 未结 5 949
挽巷
挽巷 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:52

    In case this is useful to someone, here is what I ended up doing:

    from flask import request
    
    class Parser(object):
    
      sep = ';'
    
      # ...
    
      def filter_query(self, query):
        model_class = self._get_model_class(query) # returns the query's Model
        raw_filters = request.args.getlist('filter')
        for raw in raw_filters:
          try:
            key, op, value = raw.split(self.sep, 3)
          except ValueError:
            raise APIError(400, 'Invalid filter: %s' % raw)
          column = getattr(model_class, key, None)
          if not column:
            raise APIError(400, 'Invalid filter column: %s' % key)
          if op == 'in':
            filt = column.in_(value.split(','))
          else:
            try:
              attr = filter(
                lambda e: hasattr(column, e % op),
                ['%s', '%s_', '__%s__']
              )[0] % op
            except IndexError:
              raise APIError(400, 'Invalid filter operator: %s' % op)
            if value == 'null':
              value = None
            filt = getattr(column, attr)(value)
          query = query.filter(filt)
        return query
    

    This covers all SQLAlchemy column comparators:

    • eq for ==
    • lt for <
    • ge for >=
    • in for in_
    • like for like
    • etc.

    The exhaustive list with their corresponding names can be found here.

提交回复
热议问题