Code Overview#

pgAdminの大部分は、バックエンドでFlaskフレームワークを使用して書かれたPython Webアプリケーションであり、フロントエンドでCSS3、ReactJSを使用したHTML5を使用して書かれています。デスクトップランタイムは、Electronを使用して作成されたWebアプリケーションよりもデスクトップアプリケーションを好むユーザーのために含まれています。

ランタイム#

ランタイムは、ブラウザとPythonサーバーを統合してスタンドアロンアプリケーションを作成するElectronに基づいています。ソースコードは、ソースツリーの /runtime ディレクトリにあります。

Webアプリケーション#

WebアプリケーションはpgAdminの大部分を形成し、ソースツリーの /web ディレクトリにあります。メインファイルは pgAdmin4.py で、ビルトインスタンドアロンWebサーバーを実行するために使用できます、または運用用のWSGIアプリケーションとして使用できます。

構成#

コアアプリケーション構成は config.py にあります。このファイルには、アプリケーションの構成可能なすべての設定と、その使用の説明が含まれています。 Webサーバーに展開する前に、さまざまな設定を構成することが重要です。これらは config.py または config.py config.py ドキュメントを参照してオーバーライドして、メイン構成ファイルの変更を回避できます。

ユーザー設定#

デスクトップモードで実行されている場合、pgAdminには、デスクトップユーザーに使用される単一のデフォルトのユーザーアカウントがあります。サーバーモードで実行されている場合、アプリケーションを使用する前にログインが必要なユーザーの数は無制限です。 pgAdminは、 Flask-Security モジュールを利用してアプリケーションのセキュリティとユーザーを管理し、セルフサービスのパスワードリセットやパスワード変更などのオプションを提供します。

デスクトップモードでもサーバーモードでも、各ユーザーの設定はSQLite OR外部データベースに保存されます。ユーザーアカウントの保存にも使用されます。これは、最初に setup.py スクリプトを使用して作成されます。これは、データベースファイルとスキーマを作成し、最初のユーザーアカウント管理者権限とそれらのデフォルトサーバーグループを追加します。 setup.py テーブルは、ユーザーの構成設定をキーと値の方法で保存するためにも使用されます。必須ではありませんが、LinuxまたはMacのpgAdmin 3設定ファイルと同様に、設定キーまたは名前は、通常、スラッシュを使用して人工的に名前空間値にフォーマットされます。

setup.py を実行する前に、ローカル構成をセットアップする必要があることに注意してください。ローカル構成は、特にデスクトップモードとサーバーモードに関して、スクリプトがデータベースをセットアップする方法を決定します。

pgAdminコア#

pgAdminの中心部は pgadmin パッケージです。これには、Jinjaエンジンが使用するグローバルに利用可能なHTMLテンプレートと、複数のモジュールで使用される画像、Javascript、CSSファイルなどのグローバル静的ファイルが含まれています。

パッケージの作業は、コンストラクター __init__.py で処理されます。これは、ロギングと認証のセットアップ、他のモジュールの動的ロード、およびその他のいくつかのタスクを担当します。

モジュール#

機能ユニットは、モジュールの追加を介してpgAdminに追加されます。これらはクラスのPythonオブジェクトインスタンスであり、 web/pgadmin/utils.py にあるPgAdminModuleクラスFlask Blueprint実装を継承します。他のモジュール主にデフォルトモジュールブラウザを利用するためのさまざまなフックポイントを提供します。

モジュールとして認識されるには、Pythonパッケージを作成する必要があります。これは次のことを行う必要があります。

  1. web/pgadmin/ ディレクトリ内に配置され、

  2. pgadmin.utils.PgAdminModuleクラスを実装します

  3. そのパッケージ内の特定のクラスを表すインスタンス変数通常は blueprint と呼ばれます。

各モジュールは、実装するブループリントの template および template ディレクトリを定義する場合があります。名前の衝突を回避するには、テンプレートを指定したテンプレートディレクトリ内のディレクトリの下に保存し、モジュール自分自身にちなんで名前を付ける必要があります。たとえば、 template モジュールは、テンプレートを template に保存します。これは、2番目のモジュール名を省略できる静的ファイルには適用されません。

views モジュールは、ブループリントの定義に加えて、通常、クライアントの要求に応答してレンダリングされるすべてのビューを定義します。これらのビューのREST API URLを提供する必要があります。これらには、適切なルートとセキュリティデコレータを含める必要があります。 NodeViewクラスを見てください。これは、FlaskのMethodViewと同じアプローチを使用します。 views にあります。この特定のクラスは、ブラウザノードでのさまざまな操作のためのREST API URLを作成するために使用されます。つまり、リスト、作成、更新、削除、子取得、そのノードの統計/リバースSQL/依存関係/依存リストを取得します。他の目的に同じクラスを使用することもできます。そのクラスを継承し、メンバー変数操作、parent_ids、ids、node_typeをオーバーロードし、PgAdminModuleインスタンスを使用してノードビューとして登録するだけです。

ほとんどのpgAdminモジュールは、PgAdminModuleクラスが提供する hooks も実装します。これは、モジュールをアプリケーションの残りの部分に統合するためのフックポイントを提供する責任があります。たとえば、フックは、レンダリングされたページにどのCSSファイルを含める必要があるか、またはどのメニューオプションを含める必要があるか、およびそれらが何を行うかを呼び出し元に指示します。 。フックポイントが必要でない場合は、存在する必要はありません。それらを使用する前に、それらが存在することを確認するのは呼び出し者の責任です。

現在実装されているフックは次のとおりです。

class MyModule(PgAdminModule):
    """
    This is class implements the pgadmin.utils.PgAdminModule, and
    implements the hooks
    """

    ...

    def get_own_stylesheets(self):
        """
        Returns:
            list: the stylesheets used by this module, not including any
                  stylesheet needed by the submodules.
        """
        return [url_for('static', 'css/mymodule.css')]

    def get_own_javascripts(self):
        """
        Returns:
            list of dict:
            - contains the name (representation for this javascript
              module), path (url for it without .js suffix), deps (array of
              dependents), exports window object by the javascript module,
              and when (would you like to load this javascript), etc
              information for this module, not including any script needed
              by submodules.
        """
        return [
            {
                'name': 'pgadmin.extension.mymodule',
                'path': url_for('static', filename='js/mymodule'),
                'exports': None,
                'when': 'server'
                }
            ]

    def get_own_menuitems(self):
        """
        Returns:
            dict: the menuitems for this module, not including
                  any needed from the submodules.
        """
        return {
            'help_items': [
                MenuItem(
                    name='mnu_mymodule_help',
                    priority=999,
                    # We need to create javascript, which registers itself
                    # as module
                    module="pgAdmin.MyModule",
                    callback='about_show',
                    icon='fa fa-info-circle',
                    label=gettext('About MyModule'
                    )
                ]
            }
    def get_panels(self):
        """
        Returns:
            list: a list of panel objects to add implemented in javascript
                  module
        """
        return []
    ...



blueprint = MyModule('mymodule', __name__, static_url_path='/static')

pgAdminモジュールには、必要に応じて、目的を達成するために必要な追加のPythonモジュールが含まれる場合があります。他の動的にロードされたモジュールを参照することもできますが、定義されたフックポイントを使用し、特定のモジュールが存在しないイベントに正常に失敗する必要があります。

ノード#

ノードはモジュールに非常に似ており、個々のノードまたはオブジェクトエクスプローラーツリービュー上のコレクションオブジェクトを表します。ノードモジュールとして認識されるには、PythonパッケージとJavaScriptモジュールを作成する必要があります。これは次のことを行う必要があります。

  1. web/pgadmin/browser/ ディレクトリ内に配置され、

  2. BrowserPluginModuleを実装し、ノードビューを登録します。これは、必要なREST APIを公開します

  3. クラスオブジェクトのインスタンス

フロントエンド#

pgAdminは、フロントエンド実装にJavaScriptを広範に使用します。 require.jsを使用して遅延ロードまたは必要な場合にのみロードを許可し、ReactJSとCSS、およびUIのルックアンドフィール用のマテリアルUIを使用します。各モジュールを可能な限り小さなチャンクに分割しました。すべてのJavaScriptモジュールをロードする必要はありません。つまり、データベースのJavaScriptモジュールのロードは、サーバーノードが完全にロードされた場合にのみ意味があります。 jsなど、コードの理解を深めます。