Skip to content

Bug: if the field is excluded and the field is a List[str], the filter interprets it as a str #633

@RazuvaevDD

Description

@RazuvaevDD

example:

It's work:

from typing import Optional, Union
from fastapi_filter.contrib.sqlalchemy import Filter
from sqlalchemy.sql.expression import exists, literal_column, select
from sqlalchemy.sql.functions import func, Select
from sqlalchemy.orm.query import Query

from app.models.product_model import Product


class ProductFilter(Filter):
    id: Optional[str] = None
    pupu: Optional[str] = None
    lala: Optional[str] = None
    name__ilike: Optional[str] = None
    show_last: Optional[bool] = None
    order_by: Optional[list[str]] = None

    class Constants(Filter.Constants):
        model = Product

class ProductFilterExtended(ProductFilter):
    tags__in: Optional[list[str]] = None

    class Constants(ProductFilter.Constants):
        exclude = ['tags__in']

    def filter(self, query: Union[Query, Select]) -> Query:
        tags_value = self.tags__in
        self.tags__in = None

        query = super().filter(query)

        self.tags__in = tags_value

        if self.tags__in:
            subquery = (
                select(1)
                .select_from(func.unnest(func.coalesce(Product.tags, [])).alias('tgs'))
                .where(literal_column('tgs').in_(self.tags__in))
                .correlate(Product)
            )

            query = query.where(exists(subquery))

        return query

and it's not:

from typing import Optional, Union
from fastapi_filter.contrib.sqlalchemy import Filter
from sqlalchemy.sql.expression import exists, literal_column, select
from sqlalchemy.sql.functions import func, Select
from sqlalchemy.orm.query import Query

from app.models.product_model import Product


class ProductFilter(Filter):
    id: Optional[str] = None
    pupu: Optional[str] = None
    lala: Optional[str] = None
    name__ilike: Optional[str] = None
    show_last: Optional[bool] = None
    order_by: Optional[list[str]] = None

    class Constants(Filter.Constants):
        model = Product

class ProductFilterExtended(ProductFilter):
    tags: Optional[list[str]] = None

    class Constants(ProductFilter.Constants):
        exclude = ['tags']

    def filter(self, query: Union[Query, Select]) -> Query:
        tags_value = self.tags
        self.tags = None

        query = super().filter(query)

        self.tags = tags_value

        if self.tags:
            subquery = (
                select(1)
                .select_from(func.unnest(func.coalesce(Product.tags, [])).alias('tgs'))
                .where(literal_column('tgs').in_(self.tags))
                .correlate(Product)
            )

            query = query.where(exists(subquery))

        return query

Expected: If the field is excluded, we should not (in theory) change the prefixes and postfixes of the fields, as they are excluded
Reality: excluded field changed

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions