add sql filter "contains"

This commit is contained in:
Alexander Kalinovsky
2025-02-05 23:35:02 +01:00
parent e24f9e0f79
commit 329c1361a2
6 changed files with 42 additions and 31 deletions

View File

@@ -52,9 +52,7 @@ async def route_callback(message: Message | CallbackQuery, back: bool = True, **
app: "QBotApp" = kwargs["app"] app: "QBotApp" = kwargs["app"]
cmd = app.bot_commands.get(context.user_command.split("&")[0]) cmd = app.bot_commands.get(context.user_command.split("&")[0])
await user_handler.cammand_handler( await user_handler.cammand_handler(message=message, cmd=cmd, **kwargs)
message=message, cmd=cmd, **kwargs
)
else: else:
raise ValueError(f"Unknown command {context.command}") raise ValueError(f"Unknown command {context.command}")
else: else:

View File

@@ -166,7 +166,6 @@ async def entity_item(
) )
elif isinstance(button, InlineButton): elif isinstance(button, InlineButton):
if isinstance(button.inline_button, InlineKeyboardButton): if isinstance(button.inline_button, InlineKeyboardButton):
btn_row.append(button.inline_button) btn_row.append(button.inline_button)
elif callable(button.inline_button): elif callable(button.inline_button):
@@ -238,8 +237,16 @@ async def entity_item(
field_caption = get_callable_str( field_caption = get_callable_str(
field_descriptor.caption, field_descriptor, entity_item field_descriptor.caption, field_descriptor, entity_item
) )
if field_descriptor.caption_value:
value = get_callable_str(
field_descriptor.caption_value,
field_descriptor,
entity_item,
getattr(entity_item, field_descriptor.field_name),
)
else:
value = get_value_repr( value = get_value_repr(
value=getattr(entity_item, field_descriptor.name), value=getattr(entity_item, field_descriptor.field_name),
field_descriptor=field_descriptor, field_descriptor=field_descriptor,
locale=user.lang, locale=user.lang,
) )

View File

@@ -37,7 +37,9 @@ async def command_text(message: Message, **kwargs):
state_data = await state.get_data() state_data = await state.get_data()
kwargs["state_data"] = state_data kwargs["state_data"] = state_data
await process_command_handler(message=message, callback_data=callback_data, **kwargs) await process_command_handler(
message=message, callback_data=callback_data, **kwargs
)
@router.callback_query(ContextData.filter(F.command == CallbackCommand.USER_COMMAND)) @router.callback_query(ContextData.filter(F.command == CallbackCommand.USER_COMMAND))
@@ -50,7 +52,6 @@ async def command_callback(message: CallbackQuery, **kwargs):
async def process_command_handler(message: Message | CallbackQuery, **kwargs): async def process_command_handler(message: Message | CallbackQuery, **kwargs):
state_data: dict = kwargs["state_data"] state_data: dict = kwargs["state_data"]
callback_data: ContextData = kwargs["callback_data"] callback_data: ContextData = kwargs["callback_data"]
app: "QBotApp" = kwargs["app"] app: "QBotApp" = kwargs["app"]

View File

@@ -11,12 +11,13 @@ from typing import (
TYPE_CHECKING, TYPE_CHECKING,
) )
from pydantic import BaseModel from pydantic import BaseModel
from sqlmodel import SQLModel, BigInteger, Field, select, func, column from sqlmodel import SQLModel, BigInteger, Field, select, func, column, col
from sqlmodel.ext.asyncio.session import AsyncSession from sqlmodel.ext.asyncio.session import AsyncSession
from sqlmodel.sql.expression import SelectOfScalar from sqlmodel.sql.expression import SelectOfScalar
from sqlmodel.main import SQLModelMetaclass, RelationshipInfo from sqlmodel.main import SQLModelMetaclass, RelationshipInfo
from .descriptors import EntityDescriptor, EntityField, FieldDescriptor, Filter from .descriptors import EntityDescriptor, EntityField, FieldDescriptor, Filter
from .entity_metadata import EntityMetadata from .entity_metadata import EntityMetadata
from . import session_dep from . import session_dep
@@ -233,30 +234,33 @@ class BotEntity[CreateSchemaType: BaseModel, UpdateSchemaType: BaseModel](
cls, select_statement: SelectOfScalar[Self], static_filter: list[Filter] cls, select_statement: SelectOfScalar[Self], static_filter: list[Filter]
): ):
for sfilt in static_filter: for sfilt in static_filter:
column = col(getattr(cls, sfilt.field_name))
if sfilt.operator == "==": if sfilt.operator == "==":
condition = column(sfilt.field_name).__eq__(sfilt.value) condition = column.__eq__(sfilt.value)
elif sfilt.operator == "!=": elif sfilt.operator == "!=":
condition = column(sfilt.field_name).__ne__(sfilt.value) condition = column.__ne__(sfilt.value)
elif sfilt.operator == "<": elif sfilt.operator == "<":
condition = column(sfilt.field_name).__lt__(sfilt.value) condition = column.__lt__(sfilt.value)
elif sfilt.operator == "<=": elif sfilt.operator == "<=":
condition = column(sfilt.field_name).__le__(sfilt.value) condition = column.__le__(sfilt.value)
elif sfilt.operator == ">": elif sfilt.operator == ">":
condition = column(sfilt.field_name).__gt__(sfilt.value) condition = column.__gt__(sfilt.value)
elif sfilt.operator == ">=": elif sfilt.operator == ">=":
condition = column(sfilt.field_name).__ge__(sfilt.value) condition = column.__ge__(sfilt.value)
elif sfilt.operator == "ilike": elif sfilt.operator == "ilike":
condition = column(sfilt.field_name).ilike(f"%{sfilt.value}%") condition = column.ilike(f"%{sfilt.value}%")
elif sfilt.operator == "like": elif sfilt.operator == "like":
condition = column(sfilt.field_name).like(f"%{sfilt.value}%") condition = column.like(f"%{sfilt.value}%")
elif sfilt.operator == "in": elif sfilt.operator == "in":
condition = column(sfilt.field_name).in_(sfilt.value) condition = column.in_(sfilt.value)
elif sfilt.operator == "not in": elif sfilt.operator == "not in":
condition = column(sfilt.field_name).notin_(sfilt.value) condition = column.notin_(sfilt.value)
elif sfilt.operator == "is": elif sfilt.operator == "is none":
condition = column(sfilt.field_name).is_(None) condition = column.is_(None)
elif sfilt.operator == "is not": elif sfilt.operator == "is not none":
condition = column(sfilt.field_name).isnot(None) condition = column.isnot(None)
elif sfilt.operator == "contains":
condition = sfilt.value == column.any_()
else: else:
condition = None condition = None
if condition is not None: if condition is not None:

View File

@@ -55,10 +55,11 @@ class Filter:
"not in", "not in",
"like", "like",
"ilike", "ilike",
"is", "is none",
"is not", "is not none",
"contains",
] ]
value_type: Literal["const", "param"] value_type: Literal["const", "param"] = "const"
value: Any | None = None value: Any | None = None
param_index: int | None = None param_index: int | None = None