0

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?

solknar
  • 31
  • 5
  • [`getattr`](https://docs.python.org/3/library/functions.html#getattr)? Also, please read [this](https://stackoverflow.com/help/minimal-reproducible-example). – Daniil Fajnberg Dec 17 '22 at 19:09

0 Answers0