From 67d3a4f3590af42ce2aaeadd9fe919531da9273c Mon Sep 17 00:00:00 2001 From: jackstar12 <62219658+jackstar12@users.noreply.github.com> Date: Mon, 31 Jul 2023 10:21:30 +0200 Subject: [PATCH] remove nested filters (#1843) * remove nested filters * remove from openapi schema aswell --- lnbits/db.py | 30 +++++------------------------- lnbits/helpers.py | 17 ++--------------- 2 files changed, 7 insertions(+), 40 deletions(-) diff --git a/lnbits/db.py b/lnbits/db.py index 70b5947bc..fb7e79949 100644 --- a/lnbits/db.py +++ b/lnbits/db.py @@ -375,7 +375,6 @@ class Page(BaseModel, Generic[T]): class Filter(BaseModel, Generic[TFilterModel]): field: str - nested: Optional[List[str]] op: Operator = Operator.EQ values: list[Any] @@ -390,55 +389,36 @@ class Filter(BaseModel, Generic[TFilterModel]): split = key[:-1].split("[") if len(split) != 2: raise ValueError("Invalid key") - field_names = split[0].split(".") + field = split[0] op = Operator(split[1]) else: - field_names = key.split(".") + field = key op = Operator("eq") - field = field_names[0] - nested = field_names[1:] - if field in model.__fields__: compare_field = model.__fields__[field] values = [] for raw_value in raw_values: - # If there is a nested field, pydantic expects a dict, so the raw value is turned into a dict before - # and the converted value is extracted afterwards - for name in reversed(nested): - raw_value = {name: raw_value} - validated, errors = compare_field.validate(raw_value, {}, loc="none") if errors: raise ValidationError(errors=[errors], model=model) - - for name in nested: - if isinstance(validated, dict): - validated = validated[name] - else: - validated = getattr(validated, name) - values.append(validated) else: raise ValueError("Unknown filter field") - return cls(field=field, op=op, nested=nested, values=values, model=model) + return cls(field=field, op=op, values=values, model=model) @property def statement(self): - accessor = self.field - if self.nested: - for name in self.nested: - accessor = f"({accessor} ->> '{name}')" if self.model and self.model.__fields__[self.field].type_ == datetime.datetime: placeholder = Compat.timestamp_placeholder else: placeholder = "?" if self.op in (Operator.INCLUDE, Operator.EXCLUDE): placeholders = ", ".join([placeholder] * len(self.values)) - stmt = [f"{accessor} {self.op.as_sql} ({placeholders})"] + stmt = [f"{self.field} {self.op.as_sql} ({placeholders})"] else: - stmt = [f"{accessor} {self.op.as_sql} {placeholder}"] * len(self.values) + stmt = [f"{self.field} {self.op.as_sql} {placeholder}"] * len(self.values) return " OR ".join(stmt) diff --git a/lnbits/helpers.py b/lnbits/helpers.py index f1be5b603..f1075b177 100644 --- a/lnbits/helpers.py +++ b/lnbits/helpers.py @@ -4,11 +4,7 @@ from typing import Any, List, Optional, Type import jinja2 import shortuuid -from pydantic.schema import ( - field_schema, - get_flat_models_from_fields, - get_model_name_map, -) +from pydantic.schema import field_schema from lnbits.jinja2_templating import Jinja2Templates from lnbits.requestvars import g @@ -102,20 +98,11 @@ def generate_filter_params_openapi(model: Type[FilterModel], keep_optional=False :param keep_optional: If false, all parameters will be optional, otherwise inferred from model """ fields = list(model.__fields__.values()) - models = get_flat_models_from_fields(fields, set()) - namemap = get_model_name_map(models) params = [] for field in fields: - schema, definitions, _ = field_schema(field, model_name_map=namemap) - - # Support nested definition - if "$ref" in schema: - name = schema["$ref"].split("/")[-1] - schema = definitions[name] + schema, _, _ = field_schema(field, model_name_map={}) description = "Supports Filtering" - if schema["type"] == "object": - description += f". Nested attributes can be filtered too, e.g. `{field.alias}.[additional].[attributes]`" if ( hasattr(model, "__search_fields__") and field.name in model.__search_fields__