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 ...
随机推荐
- Rsync远程同步知识点总结
Rsync: 简介:是一个开源的快速备份工具.可以在不同主机之间镜像同步整个目录,支持增量备份,保持链接(硬链接.软连接)和权限,且采用优化同步算法,传输前执行压缩(传输过程中效率加快了,但是会增加c ...
- 配置NVIDIA Container Runtime和容器运行GPUStack教程
GPUStack 是一个设计用于运行大模型的开源 GPU 集群管理器,提供私有部署的大模型服务,支持大语言模型.Embedding 文本嵌入模型.Reranker 重排序模型.Vision 多模态模型 ...
- 鸿蒙NEXT开发案例:随机数生成
[引言] 本项目是一个简单的随机数生成器应用,用户可以通过设置随机数的范围和个数,并选择是否允许生成重复的随机数,来生成所需的随机数列表.生成的结果可以通过点击"复制"按钮复制到剪 ...
- apt安装后需要移除的问题
之前记录了 apt-get remove 的命令,现在了解到原来还有 apt-get purge 的命令 这个命令可以清除配置数据 看来我们要转变一下,将来尽量用这个purge 了不然又使用清除 au ...
- 关于开启了auth的站点如何使用curl访问
有的站点开了 auth 如何访问呢 可以直接这样 将 用户名密码放入URL中 http://username:password@host:8080/index.html 即可.
- .NET使用Umbraco CMS快速构建一个属于自己的内容管理系统
前言 今天大姚给大家分享一个.NET开源.免费(MIT License).功能强大.灵活易用的内容管理系统:Umbraco CMS.本文将介绍在.NET中如何使用Umbraco CMS快速构建一个属于 ...
- MySQL原理简介—5.存储模型和数据读写机制
大纲 1.为什么不能直接更新磁盘上的数据 2.为什么要引入数据页的概念 3.一行数据在磁盘上是如何存储的 4.一行数据中的NULL值是如何处理的 5.一行数据的数据头存储的是什么 6.一行数据的真实数 ...
- 使用Tailwind CSS的几个小Tips
前情 Tailwind CSS 是一个原子类 CSS 框架,它将基础的 CSS 全部拆分为原子级别.它的工作原理是扫描所有 HTML 文件.JavaScript 文件以及任何模板中的 CSS 类名,然 ...
- 【读书笔记】 深入理解JVM第三版 JVM 运行时数据区
JVM 内存管理 堆 (Heap)线程共享 方法区 (Method Area)线程共享 虚拟机栈(VM Stack) 线程私有 本地方法栈 (Native Method Stack)线程私有 程序计数 ...
- 2024年1月Java项目开发指南14:关于post中的body和param以及java中的@RequestBody和@RequestParam
在HTTP请求中,POST方法通常用于向服务器发送数据,这些数据可以在请求的body中,也可以在URL的param中.不过,这两者的使用方式和适用场景是不同的. Body:在POST请求中,body主 ...