使用自定义参数方式实现 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查询的更多相关文章

  1. SQL Server-聚焦深入理解动态SQL查询(三十二)

    前言 之前有园友一直关注着我快点出SQL Server性能优化系列,博主我也对性能优化系列也有点小期待,本来打算利用周末写死锁以及避免死锁系列的接着进入SQL Server优化系列,但是在工作中长时间 ...

  2. SQL Server-聚焦sp_executesql执行动态SQL查询性能真的比exec好?

    前言 之前我们已经讨论过动态SQL查询呢?这里为何再来探讨一番呢?因为其中还是存在一定问题,如标题所言,很多面试题也好或者有些博客也好都在说在执行动态SQL查询时sp_executesql的性能比ex ...

  3. 一步步学Mybatis-怎么样实现动态SQL查询(6)

    上一章我们已经讲完了关于Mybatis的分页用法,其实MyBatis 还具有的一个强大的特性之一通常是它的动态 SQL 能力. 如果你有使用 JDBC 或其他 相似框架的经验,你就明白要动态的串联 S ...

  4. 获取动态SQL查询语句返回值(sp_executesql)

    在写存储过程时经常会遇到需要拼接SQL语句的情况,一般情况下仅仅是为了执行拼接后的语句使用exec(@sql)即可. 而今天的一个存储过程却需要获取动态SQL的查询结果. 需求描述:在某表中根据Id值 ...

  5. SQL Server 2012 - 动态SQL查询

    动态SQL的两种执行方式:EXEC @sql 和 EXEC sys.sp_executesql @sql DECLARE @c_ids VARCHAR(200) SET @c_ids ='1,2' - ...

  6. Mybatis中多个参数的问题&&动态SQL&&查询结果与类的对应

    ### 1. 抽象方法中多个参数的问题 在使用MyBatis时,接口中的抽象方法只允许有1个参数,如果有多个参数,例如: Integer updatePassword( Integer id, Str ...

  7. ibatis 中动态SQL查询和动态标签嵌套的使用

    ibatis 动态查询对于从事 Java EE 的开发人员来说,iBatis 是一个再熟悉不过的持久层框架了,在 Hibernate.JPA 这样的一站式对象 / 关系映射(O/R Mapping)解 ...

  8. mybatis 动态SQL查询总结

    背景 ××项目需要提供系统部分函数第三方调用接口,基于安全性和避免暴露数据库表信息的基础上进行函数接口的设计,根据第三方调用身份的权限提供某张表的自定义集合.本项目基于mybatis的持久层框架,支持 ...

  9. MyBatis 动态SQL查询,多条件,分页

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-/ ...

  10. SpringBoot中JPA使用动态SQL查询

    https://www.jianshu.com/p/f72d82e90948 可以重点关注方法二,把原生sql传入数据库去查询 好处是:更加灵活坏处是:拼接sql比较痛苦,也容易出问题,比如拼接的sq ...

随机推荐

  1. 盘点阿里、腾讯、百度大厂C#开源项目

    BAT作为互联网第一梯队的互联网公司,他们开源的项目都是发自内心地将踩过的坑和总结的经验融入到开源项目中,供业界所有人使用,希望帮助他人解决问题. 目前互联网的大厂开源的项目涉及各种语言,项目类型包含 ...

  2. youtube视频下载,youtube-dl

    []为选填,用的时候去掉[] 用pip装youtube-dl pip install -U youtube-dl [--proxy=127.0.0.1:7890] youtube-dl下载youtub ...

  3. 2022 GDOI普及组游记

    2022 GDOI普及组游记 注:传送门均为校内网址 day -4 被年级主任集中开会,给我们免了亿堆作业,灌了亿壶鸡汤,宣布了为期一(亿)周的集训开始. day -3 中午一直在复习期中(4.21- ...

  4. 命令行应用开发初学者指南:脚手架篇、UI 库和交互工具

    在日常的前端开发工作中,我们经常依赖各种命令行工具来提高效率和代码质量.例如,create-react-app 和 eslint 等工具不仅简化了项目的初始化过程,还能自动执行代码检查和格式化任务.当 ...

  5. [笔记]博弈论 & SG 函数

    一直没学结果今天被创了. 一些定义: \(\text{mex}\{S\}\):集合 \(S\) 中最小的没有出现过的非负整数. \(\oplus\):按位异或.也叫做 \(\text{xor}\). ...

  6. JavaScript 样式操作

    1.类名操作 class类名以字符串的形式存储到标签和Dom元素的属性中,标签属性为class,Dom元素属性为className,两个属性是均支持读取和修改,修改其中的一个会同步至另一个属性 cla ...

  7. 阿里云最新npm地址

    npm config set registry https://registry.npmmirror.com -g

  8. 基于知识图谱的医疗问答系统(dockerfile+docker-compose)

    目录 一.搭建 Neo4j 图数据库 1.方式选择 2.Dockerfile+docker-compose部署neo4j容器 2.1.更新 yum 镜像源 2.2.安装 docker-ce 社区版 2 ...

  9. Qt/C++音视频开发48-推流到rtsp服务器

    一.前言 之前已经打通了rtmp的推流,理论上按照同样的代码,只要将rtmp推流地址换成rtsp推流地址,然后格式将flv换成rtsp就行,无奈直接遇到协议不支持的错误提示,网上说要换成rtp,换了也 ...

  10. Qt开发经验小技巧196-200

    关于Qt延时的几种方法. void QUIHelperCore::sleep(int msec) { if (msec <= 0) { return; } #if 1 //非阻塞方式延时,现在很 ...