使用自定义参数方式实现 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. Rsync远程同步知识点总结

    Rsync: 简介:是一个开源的快速备份工具.可以在不同主机之间镜像同步整个目录,支持增量备份,保持链接(硬链接.软连接)和权限,且采用优化同步算法,传输前执行压缩(传输过程中效率加快了,但是会增加c ...

  2. 配置NVIDIA Container Runtime和容器运行GPUStack教程

    GPUStack 是一个设计用于运行大模型的开源 GPU 集群管理器,提供私有部署的大模型服务,支持大语言模型.Embedding 文本嵌入模型.Reranker 重排序模型.Vision 多模态模型 ...

  3. 鸿蒙NEXT开发案例:随机数生成

    [引言] 本项目是一个简单的随机数生成器应用,用户可以通过设置随机数的范围和个数,并选择是否允许生成重复的随机数,来生成所需的随机数列表.生成的结果可以通过点击"复制"按钮复制到剪 ...

  4. apt安装后需要移除的问题

    之前记录了 apt-get remove 的命令,现在了解到原来还有 apt-get purge 的命令 这个命令可以清除配置数据 看来我们要转变一下,将来尽量用这个purge 了不然又使用清除 au ...

  5. 关于开启了auth的站点如何使用curl访问

    有的站点开了 auth 如何访问呢 可以直接这样 将 用户名密码放入URL中 http://username:password@host:8080/index.html 即可.

  6. .NET使用Umbraco CMS快速构建一个属于自己的内容管理系统

    前言 今天大姚给大家分享一个.NET开源.免费(MIT License).功能强大.灵活易用的内容管理系统:Umbraco CMS.本文将介绍在.NET中如何使用Umbraco CMS快速构建一个属于 ...

  7. MySQL原理简介—5.存储模型和数据读写机制

    大纲 1.为什么不能直接更新磁盘上的数据 2.为什么要引入数据页的概念 3.一行数据在磁盘上是如何存储的 4.一行数据中的NULL值是如何处理的 5.一行数据的数据头存储的是什么 6.一行数据的真实数 ...

  8. 使用Tailwind CSS的几个小Tips

    前情 Tailwind CSS 是一个原子类 CSS 框架,它将基础的 CSS 全部拆分为原子级别.它的工作原理是扫描所有 HTML 文件.JavaScript 文件以及任何模板中的 CSS 类名,然 ...

  9. 【读书笔记】 深入理解JVM第三版 JVM 运行时数据区

    JVM 内存管理 堆 (Heap)线程共享 方法区 (Method Area)线程共享 虚拟机栈(VM Stack) 线程私有 本地方法栈 (Native Method Stack)线程私有 程序计数 ...

  10. 2024年1月Java项目开发指南14:关于post中的body和param以及java中的@RequestBody和@RequestParam

    在HTTP请求中,POST方法通常用于向服务器发送数据,这些数据可以在请求的body中,也可以在URL的param中.不过,这两者的使用方式和适用场景是不同的. Body:在POST请求中,body主 ...