We have a use case where we need an API which would return the filtered records fetched from the data store. The filter to be applied will be given by the user as a parameter to the API. This filter object contains the criteria. While constructing the filter the user should be able to get the suggestions on what fields are available to avoid any attribute name errors
I wanted to check if this is the correct way to take the filter through API? Or is there any other pattern which would achieve the same ?
class Criteria:
"""
Combination of operands and the operator. The operands can also be of Criteria object to create Composite Criteria
"""
def __init__(self, *args):
self.op1, self.op2, self.operator = args
def __and__(self, other):
if isinstance(other, Criteria):
return Criteria(self, other, Operator.AND)
def __str__(self):
return f"[{self.op1}, {self.op2}, {self.operator}]"
def __or__(self, other):
if isinstance(other, Criteria):
return Criteria(self, other, Operator.OR)
class Field:
def __init__(self, field_name, field_type):
self.field_name = field_name
self.type = field_type
def __eq__(self, other):
if isinstance(other, str):
print('Creating eq')
return Criteria(self.field_name, Operator.EQ, other)
class Filter(metaclass=FilterMeta):
def __init__(self):
self.criteria = None
def add_criteria(self, other):
self._add_criteria(other)
def add_or_criteria(self, other):
self._add_criteria(other, is_or=True)
def _add_criteria(self, other, is_or=False):
if self.criteria and isinstance(other, Criteria):
if is_or:
self.criteria = self.criteria | other
else:
self.criteria = self.criteria & other
elif isinstance(other, Criteria):
self.criteria = other
class PersonFilter(Filter):
name = Field(name='name', type=str)
age = Field(name='age', type=int)
The user should be able to construct the filter in the following way:
pf1 = PersonFilter()
pf1.add_criteria(pf1.name == 'abc')
pf1.add_or_criteria(pf1.age == '20')
# Would return the person records that have name as abc and age 20
- The Composite criteria can be formed by AND, OR, NOT
- The criteria can be added by the user using the Filter object. The filter object acts as a criteria builder(add_criteria, add_or_criteria)
- The reason for creating specific ObjectFilter is that user will give the correct attribute names. Even if the attribute name is changed in the domain object, this name will be same.