開源Superset線上設計圖表框架原始碼解析

開源Superset線上設計圖表框架原始碼解析

目的

superset是很強大的BI分析框架,有些不滿足需求的難免要二次開發,二次開發首先要讀懂它的原始碼,基於此目的把自己閱讀程式碼的一些分析分享給大家,讓大家都superset整體的原始碼有個整體的認識,然後具體到哪塊程式碼的時候,可以快速找到具體分析。

Superset是什麼?

Superset

是一款由 Airbnb 開源的“現代化的企業級 BI(商業智慧) Web 應用程式”,其透過建立和分享 dashboard,為資料分析提供了輕量級的資料查詢和視覺化方案。

支援的圖表型別非常多,如下一部分:

開源Superset線上設計圖表框架原始碼解析

進入正題,原始碼分析

後臺

spuerset 後端採用 Flask-AppBuilder, Sqlachermy, celery,pandas

Flask-AppBuilder: superset 的基本框架,登入驗證,許可權控制

pandas:資料處理

celery:定時非同步任務

sqlachermy: 資料引擎,連線DB

superset原始碼結構如下:

開源Superset線上設計圖表框架原始碼解析

bin

: 程式的入口檔案,可以不關心

common

: 程式共用的程式碼,暫不關心

connectors

: 資料庫聯結器,連線資料來源有2種類型,透過

ConnectorRegistry

連線

migration

: superset本身的資料庫 升級操作記錄

db_engine_specs,db_engines

: 連線其他資料庫的engines 比如mysql,pgsql等

examples

: 事例檔案,不關心

models

: 資料庫模型, Slice, Dashboard

views

: 檢視,core。py 存放所有得superset 開頭的介面

tasks

: celery 任務指令碼

security

: 修改許可權入口

templates, static

: 前端相關的模板, 控制元件程式碼

app。py

: superset 服務啟動,初始化入口

cli。py

: spuerset 命令

viz。py

: 重要,所有得圖表型別 後端資料處理入口

extensions。py

: 定義 celery, logger 等中介軟體

前端

開源Superset線上設計圖表框架原始碼解析

superset 前端採用 React,D3

superset-frontend/webpack。config。js

: 前端入口檔案

superset-frontend/src

: 前端重要檔案

superset-frontend/src/explore

: 檢視圖表詳情的頁面

superset-frontend/src/chart:根據圖表屬性渲染具體圖表頁面,裡面呼叫了

SuperChart

元件,而此元件屬於superset-ui前端庫,會根據後臺傳入的屬性,最終渲染出對應的圖表元件。

總結

動態圖表設計思路其實都是如此,前端會把各種圖表先寫好,內建到程式碼中,然後每個圖表都是自己唯一標示和相應的屬性,等透過拖拽設計好後,儲存的時候其實就是把圖表對應的屬性元資料資訊(描述圖表的json字串),傳送給後臺。 等預覽圖表的時候,其實就是從後臺讀取這些元資料資訊,然後給前端元件按照這些元資料資訊,找到對應的內建好的圖表元件,並渲染出來,而上面的

SuperChart

元件其實就是superset框架中的渲染元件。

前端和後臺互動原始碼分析

前端的程式碼結構中webpack。config。js 入口檔案中 定義了 以src資料夾去生成打包js檔案,webpack的功能

開源Superset線上設計圖表框架原始碼解析

會根據不同的原始碼,打包成不同的檔案,打包後的檔案是可以直接給瀏覽器執行的

後臺程式碼入口

superset/app。py

下面列出一些主要的程式碼片段,大部分都是這種的

appbuilder。add_link( “SQL Editor”, label=_(“SQL Editor”), href=“/superset/sqllab/”, category_icon=“fa-flask”, icon=“fa-flask”, category=“SQL Lab”, category_label=__(“SQL Lab”),)appbuilder。add_link( __(“Saved Queries”), href=“/savedqueryview/list/”, icon=“fa-save”, category=“SQL Lab”,)appbuilder。add_link( “Query Search”, label=_(“Query History”), href=“/superset/sqllab/history/”, icon=“fa-search”, category_icon=“fa-flask”, category=“SQL Lab”, category_label=__(“SQL Lab”),) appbuilder。add_view( SliceModelView, “Charts”, label=__(“Charts”), icon=“fa-bar-chart”, category=“”, category_icon=“”, )appbuilder。add_view( DashboardModelView, “Dashboards”, label=__(“Dashboards”), icon=“fa-dashboard”, category=“”, category_icon=“”, )

這些都是flask Appbuilder框架的內容,大概意思就是透過add_link和add_view會在介面上加入相應的選單,如果是add_link點選選單的時候就會訪問相應的連結,比如第一個,點選“SQL Editor”選單的時候,會訪問/superset/sqllab/連結傳送給後臺。

然後後臺處理/superset/sqllab/連結的後臺程式碼在哪?

在superset/view/core。py檔案中,程式碼如下:

@has_access@event_logger。log_this@expose(“/sqllab/”, methods=[“GET”, “POST”])def sqllab(self) -> FlaskResponse: “”“SQL Editor”“” payload = { “defaultDbId”: config[“SQLLAB_DEFAULT_DBID”], “common”: common_bootstrap_payload(), **self。_get_sqllab_tabs(g。user。get_id()), } form_data = request。form。get(“form_data”) if form_data: try: payload[“requested_query”] = json。loads(form_data) except json。JSONDecodeError: pass payload[“user”] = bootstrap_user_data(g。user) bootstrap_data = json。dumps( payload, default=utils。pessimistic_json_iso_dttm_ser ) return self。render_template( “superset/basic。html”, entry=“sqllab”, bootstrap_data=bootstrap_data )

上面的註解都是flask框架的東西,定義了處理/sqllab請求的方法,其中render_template是flask框架渲染模板的方法,裡面傳入兩個引數一個entry=“sqllab”和bootstrap_data,最後會把渲染後臺的頁面返回給後臺。

這裡再詳細看下模板渲染,先看下superset/basic。html這個模板檔案,預設的flask框架的模板都在原始碼的templates目錄下,這裡是templates/superset/basic。html,這裡貼上核心程式碼如下:

{% block body %}

開源Superset線上設計圖表框架原始碼解析
{% endblock %}// ————————————————{% block tail_js %} {% if not standalone_mode %} {{ js_bundle(‘menu’) }} {% endif %} {% if entry %} {{ js_bundle(entry) }} {% endif %} {% include “tail_js_custom_extra。html” %} {% endblock %}

上面一部分的程式碼定義了一個id=app的div,用過前端react或vue框架的都知道,這個是前端js檔案渲染的入口,無論是vue還是react生成的js檔案都會繫結到一個id=app的div下面的。

下面那塊程式碼會js_bundle(entry),其中透過上面分析entry是sqllab,他會從目錄中到到前端透過webpack打包好的js_bundle檔案,這裡的sqllab在前面的webpack。config。js中已經定義了,這裡再貼上一下吧

開源Superset線上設計圖表框架原始碼解析

可以看到裡面有sqlab,最終後臺程式碼

return self。render_template( “superset/basic。html”, entry=“sqllab”, bootstrap_data=bootstrap_data )

就是根據模板把前端程式碼/src/sqllab/index。jsx打包生成的對應js程式碼,嵌入到了模板中,然後返回給前端顯示了。

後續頁面中的具體請求都是rest api請求,後臺對應的程式碼如下:

開源Superset線上設計圖表框架原始碼解析

結構都很類似,都有api。py,dao。py等,其中api。py就是處理頁面中發起的rest api請求的(其實最終透過ajax),到時候具體問題具體分析即可。

總結

superset框架app。py中定義了介面上各個選單按鈕的功能跳轉連結,然後具體連結的後臺處理在views/core。py中,它會繼續根據templates模板渲染出結果給前端顯示,模板中會根據傳入的引數來找到對應的前端webpack打包好的檔案(不一定都是這樣,這些只是其中的一部分)。

它這個前後端分離跟之前的還是有點區別的,並不是把打包好的前端程式碼透過nginx訪問的,他還是透過python程式碼訪問的,模板的方式嵌入。