{"id":5181,"date":"2024-09-11T20:59:03","date_gmt":"2024-09-11T12:59:03","guid":{"rendered":"http:\/\/xinblog.ltd\/?p=5181"},"modified":"2024-09-27T15:51:10","modified_gmt":"2024-09-27T07:51:10","slug":"4-superset-%e5%90%af%e5%8a%a8%e6%b5%81%e7%a8%8b","status":"publish","type":"post","link":"http:\/\/xinblog.ltd\/?p=5181","title":{"rendered":"4.Superset \u542f\u52a8\u6d41\u7a0b"},"content":{"rendered":"<p>Superset \u5982\u4f55\u542f\u52a8\u7684<\/p>\n<p>\u5bf9\u4e8eSuperset\u7684\u542f\u52a8\uff0c\u5176\u672c\u8d28\u4e0a\u8fd8\u662f\u7c7b\u4f3c\u542f\u52a8\u4e00\u4e2aFlask\u6846\u67b6<\/p>\n<p>\u7531\u4e8e\u6211\u4eec\u524d\u4e24\u7ae0\u5df2\u7ecf\u8bb2\u8fc7\u4e86\u5982\u4f55\u521d\u59cb\u5316menu\u548capi\uff0c\u5728\u8fd9\u4e00\u7ae0\u4e4b\u4e2d\uff0c\u9700\u8981\u6211\u4eec\u4ee5\u542f\u52a8Superset\u4e3a\u8109\u7edc\u3002\u5c06\u4ed6\u4eec\u4e32\u8054\u8d77\u6765\u3002<\/p>\n<p>\u9996\u5148\u662f\u542f\u52a8\u76f8\u5173\u4ee3\u7801\uff0c\u5fc5\u7136\u4f4d\u4e8eapp.py\u4e0b<\/p>\n<p>\u662f\u5bf9\u5e94\u7684create_app<\/p>\n<table>\n<tr>\n<td>\n  def create_app() -&gt; Flask:<\/p>\n<p>app = SupersetApp(__name__)<\/p>\n<p>try:<\/p>\n<p># Allow user to override our config completely<\/p>\n<p>config_module = os.environ.get(&#8220;SUPERSET_CONFIG&#8221;, &#8220;superset.config&#8221;)<\/p>\n<p>app.config.from_object(config_module)<\/p>\n<p>app_initializer = app.config.get(&#8220;APP_INITIALIZER&#8221;, SupersetAppInitializer)(app)<\/p>\n<p>app_initializer.init_app()<\/p>\n<p>return app<\/p>\n<p># Make sure that bootstrap errors ALWAYS get logged<\/p>\n<p>except Exception as ex:<\/p>\n<p>logger.exception(&#8220;Failed to create app&#8221;)<\/p>\n<p>raise ex<\/td>\n<\/tr>\n<\/table>\n<p>\u4e3b\u8981\u662f\u5728\u5176\u4e2d\u5229\u7528app_initializer\u8c03\u7528 init_app\u51fd\u6570<\/p>\n<p>\u5728init_app\u51fd\u6570\u4e2d\uff0c<\/p>\n<table>\n<tr>\n<td>\n  def init_app(self) -&gt; None:<\/p>\n<p><em>&#8220;&#8221;&#8221;<br \/>\nMain entry point which will delegate to other methods in<br \/>\norder to fully init the app<br \/>\n&#8220;&#8221;&#8221;<br \/>\n<\/em>self.pre_init()<\/p>\n<p>self.check_secret_key()<\/p>\n<p># Configuration of logging must be done first to apply the formatter properly<\/p>\n<p>self.configure_logging()<\/p>\n<p># Configuration of feature_flags must be done first to allow init features<\/p>\n<p># conditionally<\/p>\n<p>self.configure_feature_flags()<\/p>\n<p>self.configure_db_encrypt()<\/p>\n<p>self.setup_db()<\/p>\n<p>self.configure_celery()<\/p>\n<p>self.enable_profiling()<\/p>\n<p>self.setup_event_logger()<\/p>\n<p>self.setup_bundle_manifest()<\/p>\n<p>self.register_blueprints()<\/p>\n<p>self.configure_wtf()<\/p>\n<p>self.configure_middlewares()<\/p>\n<p>self.configure_cache()<\/p>\n<p>with self.superset_app.app_context():<\/p>\n<p>self.init_app_in_ctx()<\/p>\n<p>self.post_init()<\/td>\n<\/tr>\n<\/table>\n<p>\u5728\u5176\u4e2d\uff0c\u5206\u522b\u8fdb\u884c\u4e86\u65e5\u5fd7\u5bf9\u8c61\u7684\u521b\u5efa\uff0c\u6570\u636e\u5e93\u7684\u914d\u7f6e\uff0c\u5b9a\u65f6\u4efb\u52a1\u7684\u914d\u7f6e<\/p>\n<p>\u6700\u540e\u8c03\u7528init_app_in_ctx<\/p>\n<table>\n<tr>\n<td>\n  def init_app_in_ctx(self) -&gt; None:<\/p>\n<p><em>&#8220;&#8221;&#8221;<br \/>\nRuns init logic in the context of the app<br \/>\n&#8220;&#8221;&#8221;<br \/>\n<\/em>self.configure_fab()<\/p>\n<p>self.configure_url_map_converters()<\/p>\n<p>self.configure_data_sources()<\/p>\n<p>self.configure_auth_provider()<\/p>\n<p>self.configure_async_queries()<\/p>\n<p>self.configure_ssh_manager()<\/p>\n<p>self.configure_stats_manager()<\/p>\n<p># Hook that provides administrators a handle on the Flask APP<\/p>\n<p># after initialization<\/p>\n<p>flask_app_mutator = self.config[&#8220;FLASK_APP_MUTATOR&#8221;]<\/p>\n<p>if flask_app_mutator:<\/p>\n<p>flask_app_mutator(self.superset_app)<\/p>\n<p>if feature_flag_manager.is_feature_enabled(&#8220;TAGGING_SYSTEM&#8221;):<\/p>\n<p>register_sqla_event_listeners()<\/p>\n<p>self.init_views()<\/td>\n<\/tr>\n<\/table>\n<p>\u5728\u8fd9\u91cc\u9762\uff0c\u5b9e\u73b0\u5bf9app\u7684\u6838\u5fc3\u6846\u67b6\u7684\u7ec4\u88c5\u3002<\/p>\n<p>\u9996\u5148\u662fconfigure_fab\uff0c\u5728\u5176\u4e2d\uff0c\u67e5\u770b\u7528\u6237\u662f\u5426\u6709\u81ea\u5df1\u63d0\u4f9b\u7684security_manager\u5417\uff0c\u5982\u679c\u63d0\u4f9b\u4e86\u81ea\u5b9a\u4e49\u5b89\u5168\u8ba4\u8bc1\u5668\uff0c\u90a3\u4e48\u5c31\u4f7f\u7528\u63d0\u4f9b\u7684\uff0c<\/p>\n<p>\u5e76\u4e14\u5728\u6700\u540e\uff0c\u8c03\u7528\u4e86appbuilder\u7684init_app\u51fd\u6570\u6765\u521d\u59cb\u5316app<\/p>\n<table>\n<tr>\n<td>\n  def configure_fab(self) -&gt; None:<\/p>\n<p>if self.config[&#8220;SILENCE_FAB&#8221;]:<\/p>\n<p>logging.getLogger(&#8220;flask_appbuilder&#8221;).setLevel(logging.ERROR)<\/p>\n<p>custom_sm = self.config[&#8220;CUSTOM_SECURITY_MANAGER&#8221;] or SupersetSecurityManager<\/p>\n<p>if not issubclass(custom_sm, SupersetSecurityManager):<\/p>\n<p>raise Exception(<\/p>\n<p>&#8220;&#8221;&#8221;Your CUSTOM_SECURITY_MANAGER must now extend SupersetSecurityManager,<\/p>\n<p>not FAB&#8217;s security manager.<\/p>\n<p>See [4565] in UPDATING.md&#8221;&#8221;&#8221;<\/p>\n<p>)<\/p>\n<p>appbuilder.indexview = SupersetIndexView<\/p>\n<p>appbuilder.base_template = &#8220;superset\/base.html&#8221;<\/p>\n<p>appbuilder.security_manager_class = custom_sm<\/p>\n<p>appbuilder.init_app(self.superset_app, db.session)<\/td>\n<\/tr>\n<\/table>\n<p>\u5728init_app\u4e2d\uff0c\u5219\u662f\u585e\u5165\u4e86\u6570\u636e\u5e93\u8fde\u63a5\uff0c\u4ee5\u53ca\u5c06menu\u7b49\u4fe1\u606f\u7ec4\u88c5\u5b8c\u6210\u3002<\/p>\n<p>\u7136\u540e\u56de\u5230init_app_in_ctx\u4e4b\u4e2d,\u914d\u7f6e\u4e86url_map_converters\u4e4b\u4e2d<\/p>\n<p>\u4e4b\u540e\u662f\u914d\u7f6esql alchemy\u76f8\u5173\u7684\u4fe1\u606f\u3002<\/p>\n<p>\u77e5\u9053\u6700\u540e\uff0c\u5229\u7528self.init_views()\u5bf9api\u548cviews\u8fdb\u884c\u7ec4\u88c5\u3002<\/p>\n<p>\u76f4\u5230\u8fd9\u91cc\uff0capp\u5b8c\u6210\u4e86\u7ec4\u88c5\u3002<\/p>\n<p>\u5728\u8fd4\u56de\u4e86app\u5bf9\u8c61\u4e4b\u540e\uff0c\u5229\u7528flask\u81ea\u5e26\u7684run_command\uff0c\u8fdb\u884c\u4e86\u76f8\u5173\u7684\u542f\u52a8\u3002\u5b8c\u6210\u4e86\u542f\u52a8\u5de5\u4f5c\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Superset \u5982\u4f55\u542f\u52a8\u7684  [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[41],"tags":[],"_links":{"self":[{"href":"http:\/\/xinblog.ltd\/index.php?rest_route=\/wp\/v2\/posts\/5181"}],"collection":[{"href":"http:\/\/xinblog.ltd\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/xinblog.ltd\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/xinblog.ltd\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/xinblog.ltd\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5181"}],"version-history":[{"count":1,"href":"http:\/\/xinblog.ltd\/index.php?rest_route=\/wp\/v2\/posts\/5181\/revisions"}],"predecessor-version":[{"id":5182,"href":"http:\/\/xinblog.ltd\/index.php?rest_route=\/wp\/v2\/posts\/5181\/revisions\/5182"}],"wp:attachment":[{"href":"http:\/\/xinblog.ltd\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5181"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/xinblog.ltd\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5181"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/xinblog.ltd\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5181"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}