既存の Pyramid アプリケーションの拡張

Pyramid 開発者がアプリケーションを構築する際にある制約に従っていれば、 サードパーティーはそのソースコードを修正する必要なしにアプリケーションの 振る舞いを変更することができます。ある制約に従う Pyramid アプリケーションの振る舞いは、修正なしで オーバーライド または 拡張 ができます。

そのような取り組みに関係する人々を識別するために、ここで専門用語を定義します。

開発者
オリジナルのアプリケーション開発者。
インテグレーター
不測のコンテキストの中でオリジナルのアプリケーション開発者によって 書かれたアプリケーションを再利用したい別の開発者。 さらに、彼はオリジナルのアプリケーションのソースコードを変更せずに、 オリジナルのアプリケーションを修正したいと思うかもしれません。

「拡張可能」なアプリケーションと「プラグ可能」なアプリケーションの違い

Django のような他のウェブフレームワークは、開発者が 「プラグ可能なアプリケーション」を作成することができると宣伝しています。 特定の方法でアプリケーションを作成すれば、サードパーティーの開発者によって 作成された別の任意のアプリケーションあるいはプロジェクトに合理的かつ構造化 された方法でアプリケーションを統合することができると主張します。

プラットフォームとしての Pyramid は、そのような特徴を提供すると 主張しません。プラットフォームは、任意のインテグレーターがより大きな Pyramid アプリケーションあるいはプロジェクトの中でサブコンポーネントと して使用できるような形でアプリケーションを作成してそれをパッケージ化 することができる、という保証をしていません。 Pyramid は、そのような パターンが満足に働くために必要な制約を強制しません。 Pyramid はあまり 「主張が強い」フレームワークではないので、開発者はアプリケーションを 構築するために非常に異なるパターンや技術を使用することができます。 与えられた Pyramid アプリケーションは、インテグレーターとオリジナルの 開発者が (特定のリレーショナルデータベースや ORM の使用といった) 類似した 基礎技術の選択を共有しているといった理由で、運が良ければ特定のサード パーティーインテグレーターにとっては再利用可能かもしれません。 しかし、同じアプリケーションがオリジナルの開発者と互換性のない異なる 技術選択を行なった別の開発者にとっては再利用可能ではないかもしれません。

その結果、「プラグ可能なアプリケーション」の概念は「CMS」レイヤーや 「アプリケーションサーバ」レイヤーのような Pyramid 上に構築されるレイヤー に残されます。そのようなレイヤーは「プラグ可能なアプリケーション」の 概念を可能にする、必要な「主張」 (ストレージレイヤーや、テンプレート システム、 URL をコードにマッピングするための構造化され十分ドキュメント化 された登録のパターンを強制することなど) を提供する傾向にあります。 このように、「プラグ可能なアプリケーション」は、 Pyramid 自体にプラグイン されるのではなく、代わりに Pyramid の上に書かれたシステムにプラグイン されます。

Pyramid は「プラグ可能なアプリケーション」を提供しませんが、 単一の既存のアプリケーションの拡張を可能にする豊富なメカニズムのセットを 提供 します 。そのような特徴は、基礎として Pyramid を使用して構築された フレームワークによって使用することができます。すべての Pyramid アプリケーションはプラグ可能とは限りませんが、すべて Pyramid アプリケーションは拡張可能です。

拡張可能なアプリケーションを構築するためのルール

最大限に拡張可能な Pyramid アプリケーションを構築したければ、 従うべきルールがたった1つだけあります: 開発者として、作成したあらゆる オーバーライド可能な imperative configuration を、アプリケーション の __init__.py 中の main 関数内で Configurator メソッドへの 呼び出しとしてインライン化するのではなく、 pyramid.config.Configurator.include() によって使用できる関数に 分解すべきです。例えば、こうではなく:

1
2
3
4
5
6
from pyramid.config import Configurator

if __name__ == '__main__':
    config = Configurator()
    config.add_view('myapp.views.view1', name='view1')
    config.add_view('myapp.views.view2', name='view2')

add_view の呼び出しを (再利用可能でない) if __name__ == '__main__' ブロックの外部に出して、再利用可能な関数の中に移動させてください:

1
2
3
4
5
6
7
8
9
from pyramid.config import Configurator

if __name__ == '__main__':
    config = Configurator()
    config.include(add_views)

def add_views(config):
    config.add_view('myapp.views.view1', name='view1')
    config.add_view('myapp.views.view2', name='view2')

これによって、インテグレーターがあなたの作成した設定関数を「オーバーライド パッケージ」から取捨選択 (selectively include or disinclude) することで あなたのアプリケーションに関係する設定命令を最大限に再利用できるようになります。

別の方法として、設定を拡張可能かつオーバーライド可能にする目的で ZCML を使用することもできます。アプリケーションに属する ZCML 宣言は、 必要なときに同様の方法でインテグレーターによってオーバーライドしたり拡張したり することができます。アプリケーションを設定するために ZCML を 使用するだけで、手作業による労力なしで自動的に最大限に拡張可能になります。 ZCML の使用に関する情報については pyramid_zcml を参照してください。

基本的なプラグポイント

Pyramid を使用して開発されたアプリケーションの基本的な 「プラグポイント」は、 route, ビュー, asset です。 route は pyramid.config.Configurator.add_route() メソッドを使用して行われた 宣言です。ビューは pyramid.config.Configurator.add_view() メソッドを 使用して行われた宣言です。 asset は pkg_resources APIを使用して Pyramid によってアクセスされるファイルで、例えば asset specification 経由でアクセスされる静的ファイルとテンプレート などがあります。他のディレクティブや configurator メソッドもまた route, ビュー, asset を扱います。例えば、 pyramid_handlers パッケージの add_handler ディレクティブは一つの route といくつかのビューを追加します。

既存のアプリケーションの拡張

既存のアプリケーションを拡張するためのステップは、アプリケーションが 設定デコレータと命令型コードのどちらを (または両方を) 使用しているか どうかに大きく依存します。

アプリケーションが設定デコレータを使用している場合

あなたは拡張またはオーバーライドしたい Pyramid アプリケーションを継承 しました。そのアプリケーションは pyramid.view.view_config デコレータあるいは他の configuration decoration を使用しています。

アプリケーションを単に 拡張 したければ、アプリケーションパッケージに対して scan を実行して、次に、追加のビューまたは route を登録する設定を 追加することができます。

1
2
3
if __name__ == '__main__':
    config.scan('someotherpackage')
    config.add_view('mypackage.views.myview', name='myview')

アプリケーションでの設定を オーバーライド したければ、オリジナルパッケージの scan を行なった後で pyramid.config.Configurator.commit() を実行 する必要がある かもしれません 。その後、追加のビューあるいは route を 登録する設定を追加すると、それはオーバーライドを行ないます。

1
2
3
4
if __name__ == '__main__':
    config.scan('someotherpackage')
    config.commit()
    config.add_view('mypackage.views.myview', name='myview')

一旦これが行われると、他と同じようにアプリケーションを拡張またはオーバーライド することができるはずです (アプリケーションの拡張 を参照)。

別の方法で、単に scan が起こらないようにすることもできます (pyramid.config.Configurator.scan() メソッドの呼び出しを省略する ことによって)。これは対象のアプリケーション中でオブジェクトに取り付けら れているデコレータに何もさせない結果になります。このポイントでは、 デコレータの中で行われたすべての設定を等価な命令型の設定あるいは ZCML に 変換して、その設定または ZCML を アプリケーションの拡張 で 説明されているように個別の Python パッケージに追加する必要があるでしょう。

アプリケーションの拡張

既存のアプリケーションの振る舞いを拡張またはオーバーライドするために、 古いパッケージの設定を含む新しいパッケージを作成する必要があるでしょう。 また、恐らく (ビューのような) オリジナルのパッケージ内で参照されている オーバーライドしたい種々のものの実装を作成する必要があるでしょう。

既存のアプリケーションの拡張に対する一般的なパターンはこのようなものです:

  • 新しい Python パッケージを作成する。これを行う最も簡単な方法は scaffold メカニズムを使用して、新しい Pyramid アプリケーションを作成する ことです。詳細は Creating the Project を参照してください。
  • 新しいパッケージで、ビューや他のオーバーライドされた要素 (必要に応じて テンプレートや静的 asset のような) を含む Python ファイルを作成する。
  • 新しいパッケージをオリジナルアプリケーションと同じ Python 環境に インストールする (例 $myvenv/bin/python setup.py develop または $myvenv/bin/python setup.py install)。
  • 新しいパッケージの __init__.py 中の main 関数を変更して、 pyramid.config.Configurator.include() 文あるいは scan に よってオリジナルの Pyramid アプリケーションの設定関数をインクルードする。
  • 新しいアプリケーションの __init__.py ファイルの main 関数内で 命令型の登録を使用して、新しいパッケージ内で作成された新しいビューおよび asset を接続する。この接続は、古いアプリケーションの設定関数をインクルードした 後で 行う必要があります。これらの登録は、オリジナルアプリケーションに よって行なわれた任意の登録を拡張またはオーバーライドすることができます。 ビューのオーバーライド, route のオーバーライド, および asset のオーバーライド を参照してください。

ビューのオーバーライド

あなたが行ったアプリケーションの振る舞いを オーバーライド する view configuration 宣言は、通常オーバーライドしたいオリジナル アプリケーションと同じ view predicate を持つでしょう。これらの <view> 宣言は、作成したオーバーライドパッケージの中にある「新しい」 ビューコードを指すでしょう。新しいビューコード自身は、通常オリジナル アプリケーションのビュー callable のカット&ペーストによるコピーに多少の 修正を加えたものになるでしょう。

例えば、オリジナルのアプリケーションに次のような configure_views 設定メソッドがある場合:

1
2
 def configure_views(config):
     config.add_view('theoriginalapp.views.theview', name='theview')

configure_views によって行われた最初のビュー設定命令を、オーバーライド パッケージ内でオリジナルの設定関数をロードした後にオーバーライドする ことができます:

1
2
3
4
5
6
7
from pyramid.config import Configurator
from originalapp import configure_views

if __name == '__main__':
    config = Configurator()
    config.include(configure_views)
    config.add_view('theoverrideapp.views.theview', name='theview')

この場合、 theoriginalapp.views.theview ビューは決して実行されません。 リクエストの状況にしたがってこのビューが実行される場合は、代わりに 新しいビュー theoverrideapp.views.theview が実行されます。

同様のパターンは add_view 宣言を持つアプリケーションを 拡張 する ために使用できます。単に他の述語セットに対して新しいビューを登録して、 ビューに関係する URL がページレンダリングされるようにしてください。

route のオーバーライド

route のセットアップは、現在典型的には add_route() への順序付きの呼び出し シーケンスによって行なわれます。これらの呼び出しがお互いに相対的で、 典型的にこの順序が重要なため、オーバーライドを行なう場合にはそれらの 相対的な順序を保持する必要があります。通常、これは add_route 命令を オーバーライドパッケージのファイルにすべて コピー して、必要に応じて それらを変更することを意味します。そして、オリジナルアプリケーションから すべての add_route 命令のインクルードを取り除きます。

asset のオーバーライド

asset はファイルシステム上にあるファイルで、 Python パッケージ 内で アクセス可能なものです。完全に一章が asset の説明のために割かれています: Static Assets 。この章には Overriding Assets というタイトルの節があります。この節では、 pyramid.config.Configurator.override_asset() メソッドを使用 することによってパッケージの asset を他の asset でオーバーライドする 方法について詳細に記述しています。オーバーライドを行なうために、 オーバーライドパッケージの __init__.py にそのような override_asset 呼び出しを追加してください。