Superset数据可视化报表二次开发

Superset简介

Superset是Airbnb开源的一个数据可视化工具, 能够接入Druid, Presto, Kylin等数据库或查询引擎. 提供丰富的可视化效果, 支持TB级别的数据量查询. Superset使用Flask-Appbuilder做为后端的开发框架, 提供更加灵活的登陆, 权限管理, view等定制化功能, 方便整合本身的系统以及二次开发. Superset解决了企业报表开发流程繁琐, 权限管理混乱的问题.前端

Superset 代码结构

从github下载源码后, 打开文件夹, 主要的代码逻辑都在superset路径下. 若是是经过pip 安装的, 经过which superset可查看可执行文件所在路径/usr/local/lib/python2.7/site-packages/superset, 该路径下的文件和源码一致, 以下所示. python

Superset代码结构

  • superset/bin: 该目录下的superset文件为程序的执行入口
  • superset/connectors: superset的一些数据源, table的model和view
  • superset/migration: 存放superset db schema升级和版本变迁
  • superset/models: 存放superset的数据库模型, superset的核心逻辑如Slice, Dashboard均可以在这里找到.
  • superset/staticsuperset/templates: superset前端相关的模板, 控件代码
  • superset/views: 放置superset全部的视图, 关于Slice, Dashboard和SQL Lab相关的展现, 查询, 存储, 下载等功能能够查看这里面的源码.
  • superset/__init__.py: 这里包含了Flask APP, Flask AppBuilder, SQLAlchemy, 和Security Manager的启动工做, 启动了superset的视图, 数据库链接, 安全管理等.

经过阅读superset/config.py中的代码, 若是须要自行修改配置, 建立superset_config.py文件, 并把该文件的路径export到环境变量SUPERSET_CONFIG_PATH中.git

登陆权限自定义开发

Superset登陆模块实际上是使用了F.A.B(Flask-AppBuilder的简称)的登陆认证框架. 有如下的登陆认证方式:github

AUTH_TYPE value description
0 / AUTH_OID Open ID的方式验证, 好比经过gmail, Twitter, FB第三方APP都属于这个范畴
1 / AUTH_DB 经过用户名密码的方式登陆, 登陆信息存到数据库
2 / AUTH_LDAP 经过LDAP协议进行登陆受权, 感兴趣能够搜一下LDAP协议
3 / AUTH_REMOTE_USER 从web server中得到验证, 该server能够是公司内统一使用的登录系统
4 / AUTH_OAUTH superset不支持该配置方法

以上更详细的内容能够查阅F.A.B的SecurityManager源码web

对Superset的源码进行熟悉后, 在superset/config.py中有AUTHENTICATION CONFIG配置, 将AUTH_TYPE的值写到superset_config.py并告诉superset该文件的路径, 这样就可以把本身想要修改的配置对superset源码中的配置进行替换. 我将本身写的配置信息写到~/superset/conf/superset_config.pysql

export SUPERSET_CONFIG_PATH=~/superset/conf/superset_config.py
复制代码

AUTH_REMOTE_USER 开发

在公司的平常生产中, 新增一个系统, 登陆模块通常会为了统一和安全考虑, 使用员工现有邮箱和密码做为登陆方式, 也就是经过调用remote server API(好比邮箱验证的API)的方式, 获取用户的认证信息, 认证经过就将用户信息保存到db中, 只要用户的session没有过时, 下次就能够直接访问网站. 即上面所说的AUTH_REMOTE_USER方式.数据库

1. 配置

首先在superset_config.py中配置CUSTOM_SECURITY_MANAGER, 替换superset中使用的SecurityManager. 接下来写一个MySecurityManager类去继承SecurityManager, 重写一些view和方法来定制本身想要的登陆效果.apache

from flask_appbuilder.security.manager import AUTH_REMOTE_USER
from security.security_models import MySecurityManager

# using customize MY security manager
CUSTOM_SECURITY_MANAGER = MySecurityManager

# AUTHENTICATION CONFIG
# 使用remote server的方式进行认证
AUTH_TYPE = AUTH_REMOTE_USER

# setup Public role name, no authentication needed
AUTH_ROLE_PUBLIC = 'Gamma'

# Will allow user self registration
AUTH_USER_REGISTRATION = True
复制代码

2. 继承和重写

Flask-Appbuilder中管理安全相关的类是SecurityManager, 正如该类的描述:编程

Responsible for authentication, registering security views, role and permission auto management. If you want to change anything just inherit and override, then pass your own security manager to AppBuilder.flask

它负责认证, 注册安全相关的视图, 角色和权限自动化管理. 因此开发的思路是屡清楚它的继承关系, 看看有哪些view, model或者方法是能够进行重写的, 从而实现本身想要的效果.

  • view能够简单理解为界面上能够看到的东西, model能够理解为和数据库交互相关的模型.
  • 这里还涉及面向对象, 继承, 重写等概念, 不太清楚的同窗推荐阅读<Java编程思想>, 里面对面向对象讲的很是棒!

SecurityManager继承关系图

这个过程当中我着重看了auth_remote_user相关的处理逻辑, 重写了authremoteuserview对象以及login的方法. 具体查看代码:

# -*- coding: utf-8 -*-
import logging

from flask_appbuilder.const import LOGMSG_WAR_SEC_LOGIN_FAILED
from flask_appbuilder.security.sqla.manager import SecurityManager

from security.security_views import MyAuthRemoteUserView

logger = logging.getLogger(__name__)

# 经过继承SecurityManager, 建立MySecurityManager类
class MySecurityManager(SecurityManager):
    logger.info("using customize my security manager")
    # 重写auth remote user view来实现登陆界面的逻辑控制
    # MyAuthRemoteUserView的具体代码能够查看github连接
    authremoteuserview = MyAuthRemoteUserView

    # 这个方法是经过查看SecurityManager源码中
    # 对auth_db等方法的操做逻辑, 本身稍做修改而来
    def auth_user_remote_user(self, username):
        """ this is a overwrite method REMOTE_USER user Authentication :type self: User model """
        user = self.find_user(username=username)

        # User does not exist, create one if auto user registration.
        if user is None and self.auth_user_registration:
            user = self.add_user(
    # All we have is REMOTE_USER, so we set
    # the other fields to blank.
                username=username,
                first_name=username.split('@')[0],
                last_name='-',
                email=username,
                role=self.find_role(self.auth_user_registration_role))

        # If user does not exist on the DB and not auto user registration,
        # or user is inactive, go away.
        elif user is None or (not user.is_active()):
            logger.info(LOGMSG_WAR_SEC_LOGIN_FAILED.format(username))
            return None
            
        self.update_user_auth_stat(user)
        return user
复制代码
  • MyAuthRemoteUserView: 这个实现的逻辑也比较简单, 我是但愿可以经过邮箱和密码登陆, 检查form提交数据是否准确, 重写login endpoint. 这过程当中使用的LoginForm很是好用, 也想多说几句, 这是Flask提供的widget, 能够检查用户提交的字段是否正确(好比email格式是否正确), 设置required项等功能.

以上的代码demo我已经提交到githubhttps://github.com/yamyamyuo/superset-development, 不知道我写的对你们有没有帮助, 若是有不清楚的地方, 欢迎在留言区讨论~~

结语

拖了很久, 终于把这篇文章整理出来了. 这段时间一直在看superset的源码, 感受进步很多, 阅读源码果真是提升代码能力的利器~


若是本文对你有帮助

请不要吝啬你的点赞和关注~

我会继续总结更新🍻

相关文章
相关标签/搜索