mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-19 05:09:40 +02:00
fix: Case Insensitive Query Filters (#5162)
This commit is contained in:
parent
4ecfd8ec78
commit
ad59e653da
2 changed files with 43 additions and 2 deletions
|
@ -180,6 +180,9 @@ class QueryFilterBuilderComponent:
|
|||
if v is None:
|
||||
continue
|
||||
|
||||
if isinstance(model_attr_type, sqltypes.String):
|
||||
sanitized_values[i] = v.lower()
|
||||
|
||||
if self.relationship is RelationalKeyword.LIKE or self.relationship is RelationalKeyword.NOT_LIKE:
|
||||
if not isinstance(model_attr_type, sqltypes.String):
|
||||
raise ValueError(
|
||||
|
@ -336,6 +339,9 @@ class QueryFilterBuilder:
|
|||
def _get_filter_element(
|
||||
component: QueryFilterBuilderComponent, model, model_attr, model_attr_type
|
||||
) -> sa.ColumnElement:
|
||||
if isinstance(model_attr_type, sqltypes.String):
|
||||
model_attr = sa.func.lower(model_attr)
|
||||
|
||||
# Keywords
|
||||
if component.relationship is RelationalKeyword.IS:
|
||||
element = model_attr.is_(component.validate(model_attr_type))
|
||||
|
@ -351,9 +357,9 @@ class QueryFilterBuilder:
|
|||
for v in component.validate(model_attr_type):
|
||||
element = sa.and_(element, primary_model_attr.any(model_attr == v))
|
||||
elif component.relationship is RelationalKeyword.LIKE:
|
||||
element = model_attr.like(component.validate(model_attr_type))
|
||||
element = model_attr.ilike(component.validate(model_attr_type))
|
||||
elif component.relationship is RelationalKeyword.NOT_LIKE:
|
||||
element = model_attr.not_like(component.validate(model_attr_type))
|
||||
element = model_attr.not_ilike(component.validate(model_attr_type))
|
||||
|
||||
# Operators
|
||||
elif component.relationship is RelationalOperator.EQ:
|
||||
|
|
|
@ -216,6 +216,29 @@ def test_pagination_filter_basic(query_units: tuple[RepositoryUnit, IngredientUn
|
|||
assert unit_results[0].id == unit_2.id
|
||||
|
||||
|
||||
def test_pagination_filter_string_case_insensitive(
|
||||
query_units: tuple[RepositoryUnit, IngredientUnit, IngredientUnit, IngredientUnit],
|
||||
):
|
||||
units_repo, *units = query_units
|
||||
target_unit = random.choice(units)
|
||||
|
||||
query = PaginationQuery(page=1, per_page=-1, query_filter=f'name="{target_unit.name.upper()}"')
|
||||
unit_results = units_repo.page_all(query).items
|
||||
assert len(unit_results) == 1
|
||||
assert unit_results[0].id == target_unit.id
|
||||
|
||||
upper_unit = units_repo.create(
|
||||
SaveIngredientUnit(name="mIxEd-CaSe uNiT", group_id=units_repo.group_id, use_abbreviation=True)
|
||||
)
|
||||
try:
|
||||
query = PaginationQuery(page=1, per_page=-1, query_filter=f'name="{upper_unit.name.lower()}"')
|
||||
unit_results = units_repo.page_all(query).items
|
||||
assert len(unit_results) == 1
|
||||
assert unit_results[0].id == upper_unit.id
|
||||
finally:
|
||||
units_repo.delete(upper_unit.id)
|
||||
|
||||
|
||||
def test_pagination_filter_null(unique_user: TestUser):
|
||||
database = unique_user.repos
|
||||
recipe_not_made_1 = database.recipes.create(
|
||||
|
@ -425,6 +448,18 @@ def test_pagination_filter_like(query_units: tuple[RepositoryUnit, IngredientUni
|
|||
assert unit_3.id in result_ids
|
||||
|
||||
|
||||
def test_pagination_filter_like_case_insensitive(
|
||||
query_units: tuple[RepositoryUnit, IngredientUnit, IngredientUnit, IngredientUnit],
|
||||
):
|
||||
units_repo, unit_1, *_ = query_units
|
||||
|
||||
query = PaginationQuery(page=1, per_page=-1, query_filter=r'name LIKE "%EST UNIT 1%"')
|
||||
unit_results = units_repo.page_all(query).items
|
||||
|
||||
assert len(unit_results) == 1
|
||||
assert unit_results[0].id == unit_1.id
|
||||
|
||||
|
||||
def test_pagination_filter_keyword_namespace_conflict(unique_user: TestUser):
|
||||
database = unique_user.repos
|
||||
recipe_rating_1 = database.recipes.create(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue