Create own components

Depending on what you want to build your own version from, there are different parameters and return values required to work properly.

Inside each __init__ method you can add everything as you wish, due it not being called in the validation process. Its definition is optional.

Condition

First off with conditions.

Their validation method is called check. It expects a dict from the type dict[str, Any] whereas the key (str) of the dictionary represents the name of a field and the value (Any) the corresponding value. The dict represents the entirety of all fields present in the InputFilter it is called.

The return value of the method should be bool, representing if the condition is true or false. - true: The condition is met and the validation can proceed - false: The validation is not met and the validation raises a ValidationError

Example implementation

from typing import Any

from flask_inputfilter.models import BaseCondition


class EqualCondition(BaseCondition):
    """
    Condition that checks if two fields are equal.
    """

    def __init__(self, first_field: str, second_field: str) -> None:
        self.first_field = first_field
        self.second_field = second_field

    def check(self, data: dict[str, Any]) -> bool:
        return data.get(self.first_field) == data.get(self.second_field)

Filter

The next type we look at is filters.

Their method called in the validation process is apply. It expects Any, representing the value of the specific field, it is applied to.

The return value should have the type Any, representing either the successfully filtered value or the value from the input. The filter should not raise any ValidationError, even if the value is not in the expected format to be filtered properly. Instead, it should just return the unfiltered value from the parameters. It is not a filers job to check weather a value meets the wanted format or not, that’s what validators are for.

Example implementation

from datetime import date, datetime
from typing import Any

from flask_inputfilter.models import BaseFilter


class ToDateTimeFilter(BaseFilter):
    """
    Filter that converts a value to a datetime object.
    Supports ISO 8601 formatted strings.
    """

    def apply(self, value: Any) -> datetime|Any:
        if isinstance(value, datetime):
            return value

        elif isinstance(value, date):
            return datetime.combine(value, datetime.min.time())

        elif isinstance(value, str):
            try:
                return datetime.fromisoformat(value)

            except ValueError:
                return value

        return value

Validator

The last type are the validators.

This type is the most important one, as it is the one that raises ensures the value meets the wanted format.

Their method called in the validation process is validate. It expects Any, representing the value of the specific field, it is applied to.

The return value should be None if the value meets the wanted format, and it should raise a ValidationError if the validation fails.

Example implementation

from typing import Any, Optional

from flask_inputfilter.exceptions import ValidationError
from flask_inputfilter.models import BaseValidator


class InArrayValidator(BaseValidator):
    """
    Validator that checks if a value is in a given list of allowed values.
    """

    def __init__(
        self,
        haystack: list[Any],
        strict: bool = False,
        error_message: Optional[str] = None,
    ) -> None:
        self.haystack = haystack
        self.strict = strict
        self.error_message = error_message

    def validate(self, value: Any) -> None:
        try:
            if self.strict:
                if value not in self.haystack or not any(
                    isinstance(value, type(item)) for item in self.haystack
                ):
                    raise ValidationError

            else:
                if value not in self.haystack:
                    raise ValidationError

        except ValidationError:
            raise ValidationError(
                self.error_message
                or f"Value '{value}' is not in the allowed "
                f"values '{self.haystack}'."
            )