Skip to content

Commit

Permalink
✨ [#472] add validation for 'data_attr' filter
Browse files Browse the repository at this point in the history
  • Loading branch information
annashamray committed Dec 12, 2024
1 parent 3676052 commit 052359f
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 23 deletions.
7 changes: 4 additions & 3 deletions src/objects/api/v2/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from ..constants import Operators
from ..utils import display_choice_values_for_help_text, string_to_value
from ..validators import validate_data_attrs
from ..validators import validate_data_attr, validate_data_attrs

DATA_ATTR_VALUE_HELP_TEXT = f"""A valid parameter value has the form `key__operator__value`.
`key` is the attribute name, `operator` is the comparison operator to be used and `value` is the attribute value.
Expand Down Expand Up @@ -102,7 +102,8 @@ class ObjectRecordFilterSet(FilterSet):
method="filter_data_attrs",
validators=[validate_data_attrs],
help_text=_(
"""**DEPRECATED**: Only include objects that have attributes with certain values.
"""**DEPRECATED: Use 'data_attr' instead**.
Only include objects that have attributes with certain values.
Data filtering expressions are comma-separated and are structured as follows:
%(value_part_help_text)s
Expand All @@ -120,7 +121,7 @@ class ObjectRecordFilterSet(FilterSet):

data_attr = ManyCharFilter(
method="filter_data_attr",
# validators=[validate_data_attrs],
validators=[validate_data_attr],
help_text=_(
"""Only include objects that have attributes with certain values.
Expand Down
6 changes: 4 additions & 2 deletions src/objects/api/v2/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ paths:
schema:
type: string
description: |
**DEPRECATED**: Only include objects that have attributes with certain values.
**DEPRECATED: Use 'data_attr' instead**.
Only include objects that have attributes with certain values.
Data filtering expressions are comma-separated and are structured as follows:
A valid parameter value has the form `key__operator__value`.
Expand Down Expand Up @@ -662,7 +663,8 @@ paths:
data_attrs:
type: string
description: |
**DEPRECATED**: Only include objects that have attributes with certain values.
**DEPRECATED: Use 'data_attr' instead**.
Only include objects that have attributes with certain values.
Data filtering expressions are comma-separated and are structured as follows:
A valid parameter value has the form `key__operator__value`.
Expand Down
56 changes: 39 additions & 17 deletions src/objects/api/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,32 +68,54 @@ def __call__(self, new_value, serializer_field):
raise serializers.ValidationError(self.message, code=self.code)


def validate_data_attr_value_part(value_part: str, code: str):
try:
variable, operator, val = value_part.rsplit("__", 2)
except ValueError:
message = _(
"Filter expression '%(value_part)s' doesn't have the shape 'key__operator__value'"
) % {"value_part": value_part}
raise serializers.ValidationError(message, code=code)

if operator not in Operators.values:
message = _("Comparison operator `%(operator)s` is unknown") % {
"operator": operator
}
raise serializers.ValidationError(message, code=code)

if operator not in (
Operators.exact,
Operators.icontains,
Operators.in_list,
) and isinstance(string_to_value(val), str):
message = _(
"Operator `%(operator)s` supports only dates and/or numeric values"
) % {"operator": operator}
raise serializers.ValidationError(message, code=code)


def validate_data_attrs(value: str):
# todo remove when 'data_attrs' filter is removed
code = "invalid-data-attrs-query"
parts = value.split(",")

for value_part in parts:
try:
variable, operator, val = value_part.rsplit("__", 2)
except ValueError as exc:
raise serializers.ValidationError(exc.args[0], code=code) from exc

if operator not in Operators.values:
message = _("Comparison operator `%(operator)s` is unknown") % {
"operator": operator
}
raise serializers.ValidationError(message, code=code)
validate_data_attr_value_part(value_part, code)

if operator not in (
Operators.exact,
Operators.icontains,
Operators.in_list,
) and isinstance(string_to_value(val), str):

def validate_data_attr(value: list):
code = "invalid-data-attr-query"

for value_part in value:
# check that comma can be only in the value part
if "," in value_part.rsplit("__", 1)[0]:
message = _(
"Operator `%(operator)s` supports only dates and/or numeric values"
) % {"operator": operator}
"Filter expression '%(value_part)s' doesn't have the shape 'key__operator__value'"
) % {"value_part": value_part}
raise serializers.ValidationError(message, code=code)

validate_data_attr_value_part(value_part, code)


class GeometryValidator:
code = "geometry-not-allowed"
Expand Down
1 change: 0 additions & 1 deletion src/objects/utils/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ def to_python(self, value):
if not value:
return []

# todo validator if it's list
return value


Expand Down

0 comments on commit 052359f

Please sign in to comment.