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的源碼, 感受進步很多, 閱讀源碼果真是提升代碼能力的利器~


若是本文對你有幫助

請不要吝嗇你的點贊和關注~

我會繼續總結更新🍻

相關文章
相關標籤/搜索