I am trying to plug a SQLModel table onto a dash data table, handling pagination, filtering and page count in the backend, as explained here https://dash.plotly.com/datatable/callbacks
Working code
from sqlmodel import SQLModel
from sqlmodel import select
from sqlmodel import col
from sqlmodel import Session
from typing import Dict
from typing import List
from typing import Tuple
class Foo(SQLModel, table=True):
bara: str
barb: int
filters = {'bara': ('contains ', 'toto'), 'barb': ('>', 1)}
def filter_foos(filters: Dict[str, Tuple[str, str]]):
"""
try to filter foos
"""
query = select(Foo)
if values := filters.get('bara'):
query = query.where(col(Foo.bara).contains(values[1]))
if values := filters.get('barb'):
if values[0] == '>=':
query = query.where(col(Foo.barb) >= values[1])
elif values[0] == '<=':
query = query.where(col(Foo.barb) <= values[1])
elif values[0] == '!=':
query = query.where(col(Foo.barb) != values[1])
elif values[0] == '=':
query = query.where(col(Foo.barb) == values[1])
elif values[0] == '>':
query = query.where(col(Foo.barb) > values[1])
elif values[0] == '<':
query = query.where(col(Foo.barb) < values[1])
return query
def select_relevant_db_lines(
session: Session,
limit: int,
offset: int,
filters: Dict[str, Tuple[str, str]]
) -> List:
"""
Select relevant row lines from Foo.
"""
if limit is not None and offset is not None:
return list(session.exec(filter_foos(filters).offset(offset*limit).limit(limit)))
My issue is that the filter function is awefully ugly, and not modular at all. If I have an new class
class Fooo(SQLModel, table=True):
toto: str
titi: int
tutu: int
I will hand up redoing the same filter_foos
boiler plate code
What I would like would be to have a dictionary to access Foo
class attributes, something like (pseudo-code, does not wok)
foo_attributes: Dict = {
'bara': Foo.bara
'barb': Foo.barb
}
That way I can dissociate the generic str
int
datetime
and whatnot treatment and then map them on class attributes. Something like (pseudo-code, not working)
def filter_ints(query, model_field: ???, operator: str, value: int):
"""
try to filter ints
"""
if not operator or not value:
return query
if operator == '>=':
query = query.where(col(model_field) >= value)
elif operator == '<=':
query = query.where(col(model_field) <= value)
elif operator == '!=':
query = query.where(col(model_field) != value)
elif operator == '=':
query = query.where(col(model_field) == value)
elif operator == '>':
query = query.where(col(model_field) > value)
elif operator == '<':
query = query.where(col(model_field) < value)
return query
def filter_strs(query, model_field: ???, value: int):
"""
try to filter strs
"""
if not value:
return query
query = query.where(col(model_field).contains(value))
def filter_models(model: Any, filters: Dict[str, Tuple[str, str]]):
"""
try to filter any model
"""
query = select(model)
if not filters:
return query
for key, (operator, value) in filters:
update_query(query, model, key, operator, value)
Is it possible to do such a thing, or will I have to implement one ugly method after another each time I add a new table to show in my dash app?