Skip to content

Commit

Permalink
updated null filtering logic
Browse files Browse the repository at this point in the history
  • Loading branch information
CosmoV committed Dec 11, 2023
1 parent 8c93bfa commit 5082a13
Showing 1 changed file with 22 additions and 16 deletions.
38 changes: 22 additions & 16 deletions fastapi_jsonapi/data_layers/filtering/sqlalchemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,27 @@ def __init__(self, model: Type[TypeModel], filter_: dict, schema: Type[TypeSchem
self.filter_ = filter_
self.schema = schema

def _check_can_to_be_none(self, fields: list[ModelField]) -> bool:
def _check_can_be_none(self, fields: list[ModelField]) -> bool:
"""
Return True if None is possible value for target field
"""
return not any(field_item.required for field_item in fields)

def _cast_value_with_scheme(self, field_types: List[ModelField], value: Any) -> Tuple[Any, List[str]]:
errors: List[str] = []
casted_value = None

for field_type in field_types:
try:
if isinstance(value, list): # noqa: SIM108
casted_value = [field_type(item) for item in value]
else:
casted_value = field_type(value)
except (TypeError, ValueError) as ex:
errors.append(str(ex))

return casted_value, errors

def create_filter(self, schema_field: ModelField, model_column, operator, value):
"""
Create sqlalchemy filter
Expand Down Expand Up @@ -82,25 +97,16 @@ def create_filter(self, schema_field: ModelField, model_column, operator, value)
else:
fields = [schema_field]
types = [i.type_ for i in fields]
clear_value = None
errors: List[str] = []

can_to_be_none = self._check_can_to_be_none(fields)
can_be_none = self._check_can_be_none(fields)

if value is None and can_to_be_none:
clear_value = None
else:
for i_type in types:
try:
if isinstance(value, list): # noqa: SIM108
clear_value = [i_type(item) for item in value]
else:
clear_value = i_type(value)
except (TypeError, ValueError) as ex:
errors.append(str(ex))
if value is None and can_be_none:
return getattr(model_column, self.operator)(value)

clear_value, errors = self._cast_value_with_scheme(types, value)

# Если None, при этом поле обязательное (среди типов в аннотации нет None, то кидаем ошибку)
if clear_value is None and not can_to_be_none:
if clear_value is None and not can_be_none:
raise InvalidType(detail=", ".join(errors))

return getattr(model_column, self.operator)(clear_value)
Expand Down

0 comments on commit 5082a13

Please sign in to comment.