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_dfcolumns_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)  # Создаем хеш из нашего нового объекта и возвращаем его. * Изначально статья была опубликована на Хабре в разделе Песочница, набрала плюсов и положительную карму. Это дало Артуру возможность стать полноправным автором Хабра и продолжать писать полезные статьи.