Code custom pour la pagination et les filtres avec chunking #7
This commit is contained in:
+57
-13
@@ -1,16 +1,12 @@
|
|||||||
from dash import (
|
from dash import html, dcc, dash_table, register_page, Input, Output, State, callback
|
||||||
html,
|
|
||||||
dcc,
|
|
||||||
dash_table,
|
|
||||||
register_page,
|
|
||||||
)
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
import os
|
import os
|
||||||
import polars as pl
|
import polars as pl
|
||||||
|
from src.utils import split_filter_part
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
df = pl.read_parquet(os.getenv("DATA_FILE_PARQUET_PATH"))
|
df = pl.scan_parquet(os.getenv("DATA_FILE_PARQUET_PATH"))
|
||||||
|
|
||||||
title = "Tableau"
|
title = "Tableau"
|
||||||
register_page(__name__, path="/", title=f"decp.info - {title}", name=title, order=1)
|
register_page(__name__, path="/", title=f"decp.info - {title}", name=title, order=1)
|
||||||
@@ -18,19 +14,18 @@ register_page(__name__, path="/", title=f"decp.info - {title}", name=title, orde
|
|||||||
datatable = dash_table.DataTable(
|
datatable = dash_table.DataTable(
|
||||||
cell_selectable=False,
|
cell_selectable=False,
|
||||||
id="table",
|
id="table",
|
||||||
data=df.to_dicts(),
|
|
||||||
page_size=20,
|
page_size=20,
|
||||||
page_current=0,
|
page_current=0,
|
||||||
page_action="native",
|
page_action="custom",
|
||||||
filter_action="native",
|
filter_action="custom",
|
||||||
filter_options={"case": "insensitive", "placeholder_text": "Filtrer..."},
|
# filter_options={"case": "insensitive", "placeholder_text": "Filtrer..."},
|
||||||
columns=[
|
columns=[
|
||||||
{"name": i, "id": i, "deletable": True, "selectable": False} for i in df.columns
|
{"name": i, "id": i, "deletable": True, "selectable": False} for i in df.columns
|
||||||
],
|
],
|
||||||
selected_columns=[],
|
selected_columns=[],
|
||||||
selected_rows=[],
|
selected_rows=[],
|
||||||
sort_action="native",
|
# sort_action="native",
|
||||||
sort_mode="multi",
|
# sort_mode="multi",
|
||||||
export_format="xlsx",
|
export_format="xlsx",
|
||||||
export_columns="visible",
|
export_columns="visible",
|
||||||
export_headers="ids",
|
export_headers="ids",
|
||||||
@@ -44,6 +39,7 @@ datatable = dash_table.DataTable(
|
|||||||
"whiteSpace": "normal",
|
"whiteSpace": "normal",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
data_timestamp=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
layout = [
|
layout = [
|
||||||
@@ -88,3 +84,51 @@ layout = [
|
|||||||
children=datatable,
|
children=datatable,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@callback(
|
||||||
|
Output("table", "data"),
|
||||||
|
Output("table", "data_timestamp"),
|
||||||
|
Input("table", "page_current"),
|
||||||
|
Input("table", "page_size"),
|
||||||
|
Input("table", "filter_query"),
|
||||||
|
State("table", "data_timestamp"),
|
||||||
|
)
|
||||||
|
def update_table(page_current, page_size, filter_query, data_timestamp):
|
||||||
|
print(" + + + + + + + + + + + + + + + + + + ")
|
||||||
|
print("Filter query:", filter_query)
|
||||||
|
# 1. Apply Filters
|
||||||
|
dff = df # start from the original data
|
||||||
|
if filter_query:
|
||||||
|
filtering_expressions = filter_query.split(" && ")
|
||||||
|
for filter_part in filtering_expressions:
|
||||||
|
col_name, operator, filter_value = split_filter_part(filter_part)
|
||||||
|
print("filter_value:", filter_value)
|
||||||
|
print("filter_value_type:", type(filter_value))
|
||||||
|
|
||||||
|
if operator in ("<", "<=", ">", ">="):
|
||||||
|
filter_value = int(filter_value)
|
||||||
|
if operator == "<":
|
||||||
|
dff = dff.filter(pl.col(col_name) < filter_value)
|
||||||
|
elif operator == ">":
|
||||||
|
dff = dff.filter(pl.col(col_name) > filter_value)
|
||||||
|
elif operator == ">=":
|
||||||
|
dff = dff.filter(pl.col(col_name) >= filter_value)
|
||||||
|
elif operator == "<=":
|
||||||
|
dff = dff.filter(pl.col(col_name) <= filter_value)
|
||||||
|
# these operators match polars series filter operators
|
||||||
|
|
||||||
|
elif operator == "contains":
|
||||||
|
dff = dff.filter(pl.col(col_name).str.contains("(?i)" + filter_value))
|
||||||
|
# elif operator == 'datestartswith':
|
||||||
|
# dff = dff.filter(pl.col(col_name).str.startswith(filter_value)")
|
||||||
|
|
||||||
|
# 2. Paginate Data
|
||||||
|
start_row = page_current * page_size
|
||||||
|
# end_row = (page_current + 1) * page_size
|
||||||
|
|
||||||
|
dff = dff.slice(start_row, page_size).collect()
|
||||||
|
# print("dff_sliced:", dff.select("titulaire.typeId"))
|
||||||
|
dff = dff.to_dicts()
|
||||||
|
|
||||||
|
return dff, data_timestamp + 1 # update data, update timestamp
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
operators = [
|
||||||
|
["s<", "<"],
|
||||||
|
["s>", ">"],
|
||||||
|
["scontains", "contains"],
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def split_filter_part(filter_part):
|
||||||
|
print("filter part", filter_part)
|
||||||
|
for operator_group in operators:
|
||||||
|
if operator_group[0] in filter_part:
|
||||||
|
name_part, value_part = filter_part.split(operator_group[0], 1)
|
||||||
|
name_part = name_part.strip()
|
||||||
|
value = value_part.strip()
|
||||||
|
name = name_part[name_part.find("{") + 1 : name_part.rfind("}")]
|
||||||
|
|
||||||
|
return name, operator_group[1], value
|
||||||
|
|
||||||
|
return [None] * 3
|
||||||
Reference in New Issue
Block a user