В этой статье продолжаем борьбу с фильтрами по дате в Apache Superset. Сегодня разберем, как реализовать подобие логики remove_filter в старых версиях (до 5), чтобы виртуальный датасет не оборачивался фильтрами.
В этой статье продолжаем борьбу с фильтрами по дате в Apache Superset. Сегодня разберем, как реализовать подобие логики remove_filter в старых версиях (до 5), чтобы виртуальный датасет не оборачивался фильтрами.
Обязательно прочитайте первую часть, чтобы понимать, откуда взялись на дашборде фильтры и почему они именно такие.
Довольно часто мы используем виртуальные датасеты. И порой бывает нужда как-то покастомить ту дату, которую передают фильтры. Давайте же сразу наиграем такой кейс:
Создаем виртуальный датасет запросом
select *
from messages
where 1=1
and ts > (TIMESTAMP '{{ from_dttm | default("1970-01-01", true) }}' + INTERVAL '3 days')
Предположим что нам, например, крайне важно к той дате, которую пользователь передал в фильтре, добавлять еще 3 дня.
Добавляем его на дашборд с фильтром в простой чарт "таблица" и добавляем какую-ту фильтрацию, например last week

Ну и видим боль - виртуальный датасет сверху все равно оборачивается условиями из фильтра. И это не никак не отменить, в отличие от других макросов, где есть параметр remove_filter.
Можно привести целую массу кейсов, почему это плохо. В нашем случае - фильтрация будет работать неверно, ведь мы кастомим, добавляя 3 дня, а суперсет сверху оборачивает эти условия так, что наш кастом работать будет неверно (нет условия на + 3 дня).
Рассмотрим универсальный на все случаи жизни хак.
Сперва смотрим, что возвращает макрос, если в фильтр ничего не передано и передано хоть что-то. Для этого в датасете меняем логику, оставляя только select {{from_dttm}} as res. Результаты:

Когда ничего не передано

Когда что-то передано
Видим, что если ничего не передано - None (именно питонячий None), в противном случае возвращает дату. Имея эту информацию делаем следующее:
Перехватываем то, что передано в фильтр, записываем в переменную from_dttm_fv, если в фильтр ничего не передано - записываем 1970-01-01 00:00:00. Далее кастуем это в TIMESTAMP и делаем из этого фиктивную колонку.
{% set from_dttm_fv = from_dttm | default("1970-01-01 00:00:00", true) %}
SELECT *, '{{ from_dttm_fv }}'::TIMESTAMP as fict_column
FROM messages
Теперь фиктивную колонку нужно синкнуть в датасет и дать ей разрешения (если вдруг они не дадутся)

Видим, что fict_column теперь является частью датасета, причем с типом DATETIME. Именно для этого крайне важен был каст в TIMESTAMP, и крайне важно было то, какое дефолтное значение возвращает макрос, ведь по умолчанию он возвращает None, и для обхода None мы и добавляли | default("1970-01-01 00:00:00", true). Теперь мы можем фиктивную колонку использовать в фильтрах на дашборде, а так как она имеет тип DATETIME - то и в фильтре TIME COLUMN тоже:

Видим, что мы перехватили значение фильтра, и оно точно будет удовлетворять обоим условиям, которыми суперсет оборачивает наш виртуальный датасет, так как мы берем именно from_dttm, т.е. наименьшее значение. Верхний диапазон to_dttm будет всегда выше. Поэтому оба внешних условия будут истинны. Ну а мы теперь вольны использовать перехваченное значение как угодно. Кстати, давайте и to_dttm тоже перехватим для приличия и покрутим, как нам угодно:
{% set from_dttm_fv = from_dttm | default("1970-01-01 00:00:00", true) %}
{% set to_dttm_fv = from_dttm | default("1970-01-01 00:00:00", true) %}
SELECT *
, '{{ from_dttm_fv }}'::TIMESTAMP as fict_column
FROM messages
WHERE ts > (TIMESTAMP '{{ from_dttm_fv }}' + INTERVAL '3 days')
and ts < (TIMESTAMP '{{ to_dttm_fv }}' + INTERVAL '3 days')
Ну и в результате на дашборде получим следующее:

Видим, что теперь мы вольны что угодно делать со значениями из фильтра, при этом внешние условия будут выполняться.
Примерно так выглядит типичный процесс настройки виртуального датасета:
Плачешь
Гуглишь, читаешь документацию
Пробуешь сделать
Снова плачешь
Начинаешь немного понимать, что происходит
Танцуешь с бубном
PROFIT (непонятно, почему заработало, но тебе уже все равно)

Ну а если хотите понимать суперсет еще лучше и танцевать с бубном без слез (НЕ танцевать с бубном просто не получится) - добро пожаловать на курс автора статьи.
| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | Apache Superset — боремся с фильтрами по дате. Часть 1 | 0 | 7.7 | 27-03-2026 |
| 2 | Как я встроил AI‑агента прямо в интерфейс Apache Superset и не сломал ему CSP | 1 | 8.42 | 09-08-2026 |
| 3 | Невозможно быть вне политики с Airflow Cluster Policies | 0 | 7.01 | 15-06-2026 |
| 4 | Работа с несбалансированными данными: SMOTE мёртв, что работает | 0 | 12.98 | 31-01-2026 |
| 5 | Как мы вывели в админку ошибки yt-dlp, которые жили только в логах. Bridge на 200 строк и борьба с alert-fatigue | 0 | 12.76 | 24-05-2026 |
| 6 | Airflow TaskFlow API: внутреннее устройство современного способа писать DAG-и | 0 | 10.41 | 14-05-2026 |
| 7 | Хватит засовывать всё в контейнеры: возвращаем комфорт в локальную разработку | 0 | 8.84 | 27-06-2026 |
| 8 | Gotchas With SQLite in Production | 0 | 12.11 | 03-04-2026 |
| 9 | Методы обнаружения контуров в изображении: пространственные фильтры | 0 | 10.33 | 02-05-2026 |
| 10 | Django-style фильтры поверх SQLAlchemy: зачем я написал python пакет sqlalchemy-query-manager | 0 | 11.63 | 29-06-2026 |