Superset实现动态SQL查询
使用自定义参数方式实现 superset 实现SQL动态查询
1、启用参数:config.py 设置"ENABLE_TEMPLATE_PROCESSING": True
2、当前superset v1.2版本支持的参数包括:
{{ current_username() }} 当前登录用户名
{{ current_username(add_to_cache_keys=False) }} 不从缓存中获取登录用户名,默认从缓存获取
{{ current_user_id()}} 当前登录用户ID
{{ current_user_id(add_to_cache_keys=False) }} 不从缓存中获取登录用户ID,默认从缓存获取
{{ url_param('custom_variable') }} url 参数,比如127.0.0.1:8001\dashboard?abc=123,参数就是{{ url_param('abc') }} 结果就是123
{{ cache_key_wrapper() }} 还没有弄明白啥用
{{ filter_values("字段名") }} 获取dashboard filter_box组件对某个字段的筛选结果
{{ from_dttm }} 获取dashboard filter_box组件日期筛选的开始时间
{{ to_dttm }} 获取dashboard filter_box组件日期筛选的结束时间
{{ get_filters() }} 暂时没有弄明白
除此之外,还可以自定义参数,自定义参数方法:
①修改superset/jinja_context.py文件,修改三个地方:
1 regex = re.compile(
2 r"\{\{.*("
3 r"current_user_id\(.*\)|"
4 r"current_username\(.*\)|"
5 r"current_userroles\(.*\)|"
6 r"isadmin\(.*\)|"
7 r"cache_key_wrapper\(.*\)|"
8 r"url_param\(.*\)"
9 r").*\}\}"
10 )
↑↑↑↑注意此处的 current_userroles 和 isadmin 是我自定义的,源文件没有
1 def current_user_id(self, add_to_cache_keys: bool = True) -> Optional[int]:
2 """
3 Return the user ID of the user who is currently logged in.
4
5 :param add_to_cache_keys: Whether the value should be included in the cache key
6 :returns: The user ID
7 """
8
9 if hasattr(g, "user") and g.user:
10 if add_to_cache_keys:
11 self.cache_key_wrapper(g.user.get_id())
12 return g.user.get_id()
13 return None
14
15 def current_username(self, add_to_cache_keys: bool = True) -> Optional[str]:
16 """
17 Return the username of the user who is currently logged in.
18
19 :param add_to_cache_keys: Whether the value should be included in the cache key
20 :returns: The username
21 """
22
23 if g.user and hasattr(g.user, "username"):
24 if add_to_cache_keys:
25 self.cache_key_wrapper(g.user.username)
26 return g.user.username
27 return None
28 def current_userroles(self, add_to_cache_keys: bool = True) -> Optional[str]:
29 """
30 Return the roles of the user who is currently logged in.
31
32 :param add_to_cache_keys: Whether the value should be included in the cache key
33 :returns: The userroles
34 """
35
36 if g.user and hasattr(g.user, "roles"):
37 if add_to_cache_keys:
38 user_roles = "/".join([role.name.lower() for role in list(g.user.roles)])
39 self.cache_key_wrapper(user_roles)
40 print(user_roles)
41 return user_roles
42 """admin in user_roles"""
43 return None
44
45 def isadmin(self, add_to_cache_keys: bool = True) -> Optional[str]:
46 """
47 Return the roles of the user who is currently logged in.
48
49 :param add_to_cache_keys: Whether the value should be included in the cache key
50 :returns: The userroles
51 """
52
53 if g.user and hasattr(g.user, "roles"):
54 if add_to_cache_keys:
55 user_roles = [role.name.lower() for role in list(g.user.roles)]
56 return "admin" in user_roles
57 return None
↑↑↑↑仿照系统自带的 current_username 编造自己的函数,我写了current_userroles 和 isadmin
1 class JinjaTemplateProcessor(BaseTemplateProcessor):
2 def set_context(self, **kwargs: Any) -> None:
3 super().set_context(**kwargs)
4 extra_cache = ExtraCache(self._extra_cache_keys)
5 self._context.update(
6 {
7 "url_param": partial(safe_proxy, extra_cache.url_param),
8 "current_user_id": partial(safe_proxy, extra_cache.current_user_id),
9 "current_username": partial(safe_proxy, extra_cache.current_username),
10 "current_userroles": partial(safe_proxy, extra_cache.current_userroles),
11 "isadmin": partial(safe_proxy, extra_cache.isadmin),
12 "cache_key_wrapper": partial(safe_proxy, extra_cache.cache_key_wrapper),
13 "filter_values": partial(safe_proxy, filter_values),
14 }
15 )
↑↑↑↑仿照系统自带的 current_username 编造自己的函数,我写了current_userroles 和 isadmin
就是这3个地方,但是注意,自己在第二步早的函数,返回值必须是:
1 ALLOWED_TYPES = (
2 NONE_TYPE,
3 "bool",
4 "str",
5 "unicode",
6 "int",
7 "long",
8 "float",
9 "list",
10 "dict",
11 "tuple",
12 "set",
13 )
否则会提示错误,或者自己修改这个types,我是转换,比如上面那个g.user.roles 返回的结果就不是上面类型,导致我一直不成功,最后修改了下,才可以
3、判断是否自定义成功:
在superset sql lab中执行如下代码,如果能被解析,就说明成功

4、应用案例:

在dataset里面,动态访问数据源,数据源添加where语句:select * from sales where salesname =' {{current_username()}}'
dashboard里面,通过获取筛选器的结果,然后获取其他表应当显示的数据范围:
1 select DATE,risktype,sum(num) as num from
2 (SELECT date , customerid,product,risktype ,count(*) as num
3 from v_superset_forecast_risk group by date , customerid,product,risktype ) a
4 join
5 (select distinct customer_code,product from v_superset_access
6 where name='{{ current_username() }}' )access
7 on a.customerid=access.customer_code
8 and a.product=access.product
9 and DATE_FORMAT(date,'%Y-%m')> DATE_FORMAT(date_sub(STR_TO_DATE(concat( {{ "'" + "', '".join(filter_values('yearmonthend')) + "'" }},'-01'), '%Y-%m-%d'), interval 12 month),'%Y-%m')
10 and DATE_FORMAT(date,'%Y-%m')<={{ "'" + "', '".join(filter_values('yearmonthend')) + "'" }}
11 group by DATE,risktype
因为sql里面可以使用jinja 表达式,比如判断筛选当前没有筛选的时候,获取什么数据


1 {% if isadmin() %}
2
3 select * from sales
4
5 {% else %}
6
7 select * from sales where name ='{{current_username()}}'
8
9 {% endif %}

注意{% %} 内部使用参数的时候,不需要加{{}},否则报错
通过筛选器实现模糊查询


5、官方参考文档:https://superset.apache.org/docs/installation/sql-templating
官方没有那么详细,但是里面有一些我这里可能也没有消化吸收掉,可以参考看下
总之,通过上面的自定义参数方法,和jinja表达式在sql中的应用,可以实现动态查询,解决一些无法通过页面直接交互查询结果显示的内容
另外如果你有其他应用或者自定义上的思考,欢迎留言,相互学习
Superset实现动态SQL查询的更多相关文章
- SQL Server-聚焦深入理解动态SQL查询(三十二)
前言 之前有园友一直关注着我快点出SQL Server性能优化系列,博主我也对性能优化系列也有点小期待,本来打算利用周末写死锁以及避免死锁系列的接着进入SQL Server优化系列,但是在工作中长时间 ...
- SQL Server-聚焦sp_executesql执行动态SQL查询性能真的比exec好?
前言 之前我们已经讨论过动态SQL查询呢?这里为何再来探讨一番呢?因为其中还是存在一定问题,如标题所言,很多面试题也好或者有些博客也好都在说在执行动态SQL查询时sp_executesql的性能比ex ...
- 一步步学Mybatis-怎么样实现动态SQL查询(6)
上一章我们已经讲完了关于Mybatis的分页用法,其实MyBatis 还具有的一个强大的特性之一通常是它的动态 SQL 能力. 如果你有使用 JDBC 或其他 相似框架的经验,你就明白要动态的串联 S ...
- 获取动态SQL查询语句返回值(sp_executesql)
在写存储过程时经常会遇到需要拼接SQL语句的情况,一般情况下仅仅是为了执行拼接后的语句使用exec(@sql)即可. 而今天的一个存储过程却需要获取动态SQL的查询结果. 需求描述:在某表中根据Id值 ...
- SQL Server 2012 - 动态SQL查询
动态SQL的两种执行方式:EXEC @sql 和 EXEC sys.sp_executesql @sql DECLARE @c_ids VARCHAR(200) SET @c_ids ='1,2' - ...
- Mybatis中多个参数的问题&&动态SQL&&查询结果与类的对应
### 1. 抽象方法中多个参数的问题 在使用MyBatis时,接口中的抽象方法只允许有1个参数,如果有多个参数,例如: Integer updatePassword( Integer id, Str ...
- ibatis 中动态SQL查询和动态标签嵌套的使用
ibatis 动态查询对于从事 Java EE 的开发人员来说,iBatis 是一个再熟悉不过的持久层框架了,在 Hibernate.JPA 这样的一站式对象 / 关系映射(O/R Mapping)解 ...
- mybatis 动态SQL查询总结
背景 ××项目需要提供系统部分函数第三方调用接口,基于安全性和避免暴露数据库表信息的基础上进行函数接口的设计,根据第三方调用身份的权限提供某张表的自定义集合.本项目基于mybatis的持久层框架,支持 ...
- MyBatis 动态SQL查询,多条件,分页
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-/ ...
- SpringBoot中JPA使用动态SQL查询
https://www.jianshu.com/p/f72d82e90948 可以重点关注方法二,把原生sql传入数据库去查询 好处是:更加灵活坏处是:拼接sql比较痛苦,也容易出问题,比如拼接的sq ...
随机推荐
- 2023NOIP A层联测28 T3 大眼鸹猫
2023NOIP A层联测28 T3 大眼鸹猫 比赛做出来了,但是文抄-- 思路 分析每一个 \(i\),发现其一定需要上升或下降 \(|a_i-b_i|\). 如果求出最小操作次数,然后在此基础上, ...
- NZOJ 模拟赛5
T1 逃离遗迹 根据外星人的回信,在遗迹中有分布着三样道具.当三样道具都拿走后,遗迹就很快自动毁灭,所以必须要在最短时间内离开.遗迹可以看作是由N个房间(编号1..N)和N-1条长度不等通道所组成,并 ...
- 关于linux 终端的小命令
Ubuntu 为例 ctrl alt t 新开一个终端(默认工作目录) ctrl shift t 在当前终端开一个tab (工作目录和当前tab一致 当你进入一个很深的目录的时候需要新开一个命令行 ...
- SyntaxError: non-default argument follows default argument
有时候没注意就会犯一些低级错误 问题原因 把没有默认值的形参放到了带有默认值的形参后面 解决办法 问了一下chatgpt,果然一语道破.因为python在定义函数时,在不定长参数中,默认值参数不能放在 ...
- MySQL报错注入之Xpath报错&floor函数报错
目录 前言 Xpath报错注入 updatexml()函数 extractvalue()函数 floor函数报错 count与group by的虚拟表 总结 PostGIS函数报错 ST_LatFro ...
- SQLSERVER 2019数据库(可疑) 数据修复案例
2019 数据库 , 在正常使用过程中 , 服务器突然断电 , 重新启动服务器后 , 数据库变为(可疑). [数据恢复故障分析] 由于数据库在正常读写操作过 , 服务器突然断电 , 导致数据库无法把所 ...
- GitBook之基本使用
GitBook 简介 GitBook 官网 GitBook 文档 GitBook 准备工作 安装 Node.js GitBook 是一个基于 Node.js 的命令行工具,下载安装 Node.js,安 ...
- window下cmd显示乱码
前情 最近在维护一些老项目,本地开发环境跑不起来,需要根据cmd中的报错来解决一些环境问题 坑位 在解决环境错误的时候,cmd命令行日志打印出来的是一堆乱码,导致看不清具体是什么错误 Why? cmd ...
- IOS多线程之NSOperation(1)
IOS多线程之NSOperation(1) NSOperation 是 OC 语言中基于 GCD 的面向对象的封装: 提供了一些用 GCD 不好实现的功能: 线程的生命周期由系统自动管理. NSOpe ...
- 使用 Windows Debugger 调试托管代码
使用 Windows Debugger 调试托管代码 https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugg ...