if form_data.get("viz_type") == "pivot_table_v3": # Проверяем что запрос пришел на нашу новую таблицу.
for query in self.queries:
query.row_limit = 0 # И для каждого запроса в БД уберем лимит
post_processors = {
"pivot_table": pivot_table,
"pivot_table_v2": pivot_table_v2,
"pivot_table_v3": pivot_table_v3,
"table": table,
}
processed_df = post_processor(df, form_data, datasource)
query["colnames"] = list(processed_df.columns)
query["indexnames"] = list(processed_df.index)
query["coltypes"] = extract_dataframe_dtypes(processed_df, datasource)
query["rowcount"] = len(processed_df.index)
processed_df = post_processor(df, form_data, datasource)
query["colnames"] = list(processed_df.columns)
query["coltypes"] = extract_dataframe_dtypes(processed_df, datasource)
query["rowcount"] = len(processed_df.index)
if form_data.get("server_pagination", False): # Проверяем, включена ли серверная пагинация.
page = max(form_data.get("page", 0), 0) # Достаем номер страницы, при этом проверяя, что число не отрицательное.
page_size = max(form_data.get("pageSize", 100), 1) # Достаем размер страницы, проверяя, что число не меньше 1.
processed_df = processed_df[page * page_size:(page + 1) * page_size] # Отрезаем от DataFrame необходимый отрезок.
query["indexnames"] = list(processed_df.index) # Также мы перенесли создание индекса после пагинации, так как он может отличаться от изначального.
def generate_cache_for_pivot(form_data: dict[str, Any]) -> str:
cache_dict = {k: form_data[k] for k in form_data.keys() - {'page', 'page_size', 'server_pagination'}} # Убираем из полученного объекта лишние поля и формируем новый объект.
return generate_cache_key(cache_dict) # Создаем хеш из нашего нового объекта и возвращаем его.
if form_data.get("viz_type") == "pivot_table_v3":
cache_key = generate_cache_for_pivot(form_data)
res = cache.get(cache_key)
if res:
... # Возврат с обработкой ответа из кеша, но без запроса в БД.
for query in self.queries:
query.row_limit = 0
... # Обычное выполнение запроса и его последующая обработка.
def pivot_table_v3(
df: pd.DataFrame,
form_data: Dict[str, Any],
datasource: Optional["BaseDatasource"] = None,
) -> pd.DataFrame:
"""
Pivot table v3.
"""
verbose_map = datasource.data["verbose_map"] if datasource else None
if form_data.get("granularity_sqla") == "all" and DTTM_ALIAS in df:
del df[DTTM_ALIAS]
res_df = pivot_df(
df,
rows=get_column_names(form_data.get("groupbyRows"), verbose_map),
columns=get_column_names(form_data.get("groupbyColumns"), verbose_map),
metrics=get_metric_names(form_data["metrics"], verbose_map),
aggfunc=form_data.get("aggregateFunction", "Sum"),
transpose_pivot=bool(form_data.get("transposePivot")),
combine_metrics=bool(form_data.get("combineMetric")),
show_rows_total=bool(form_data.get("rowTotals")),
show_columns_total=bool(form_data.get("colTotals")),
apply_metrics_on_rows=form_data.get("metricsLayout") == "ROWS",
)
cache_key = generate_cache_for_pivot(form_data) # Создадим ключ с помощью функции которую мы создали ранее.
cache.set(cache_key, res_df.to_dict()) # Положим получившийся DataFrame в кэш.
return res_df
columns_to_sort = form_data.get("sortByColumns") or [] # Достаем массив по которому необходимо отсортировать данные# Создаем хеш из нашего нового объекта и возвращаем его
if columns_to_sort: # Если массив существует, применяем сортировку
ascSort = form_data.get("sortAsc") or False # Достаем значение определяющие сортировать по возрастанию или убыванию.
df = df.sort_values(by=columns_to_sort, ascending=ascSort) # Сортируем DataFrame встроенной функцией сортировки.
def generate_cache_for_pivot(form_data: dict[str, Any]) -> str:
cache_dict = {k: form_data[k] for k in form_data.keys() - {'page', 'page_size', 'server_pagination', 'sortByColumns', 'sortAsc'}} # Убираем из полученного объекта лишние поля и формируем новый объект.
return generate_cache_key(cache_dict) # Создаем хеш из нашего нового объекта и возвращаем его.
* Изначально статья была опубликована на Хабре в разделе Песочница, набрала плюсов и положительную карму. Это дало Артуру возможность стать полноправным автором Хабра и продолжать писать полезные статьи.