(機械翻訳) ピラミッド構成の拡張

Pyramidでは、カスタムディレクティブを使用してConfiguratorを拡張できます。カスタムディレクティブは他のディレクティブを使用することができ、custom:term: action`を追加することができます:term: conflict resolution`に参加でき、いくつかの:term: `introspectable`オブジェクトを提供できます。

`` add_directive``を使ってコンフィグレータにメソッドを追加する

フレームワーク拡張の作者は、コンフィグレータの:meth: pyramid.config.Configurator.add_directive`メソッドを使って:term: Configurator`に任意のメソッドを追加できます。 :meth: `〜pyramid.config.Configurator.add_directive`を使うと、Pyramidコンフィギュレータを任意の方法で拡張することができ、アプリケーション固有のタスクをより簡潔に実行することができます。

:meth: `〜pyramid.config.Configurator.add_directive`メソッドは、メソッド名と呼び出し可能オブジェクトという2つの位置引数を受け取ります。呼び出し可能オブジェクトは、通常、最初の引数としてコンフィギュレータインスタンスを取り、他の任意の位置引数とキーワード引数を受け入れる関数です。例えば:

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

def add_newrequest_subscriber(config, subscriber):
    config.add_subscriber(subscriber, NewRequest)

if __name__ == '__main__':
    config = Configurator()
    config.add_directive('add_newrequest_subscriber',
                         add_newrequest_subscriber)

一旦:meth: `〜pyramid.config.Configurator.add_directive`が呼び出されると、ユーザはConfiguredatorの組み込みメソッドであるかのように、指定された名前で追加されたディレクティブを呼び出すことができます:

1
2
3
4
def mysubscriber(event):
    print(event.request)

config.add_newrequest_subscriber(mysubscriber)

:meth: 〜pyramid.config.Configurator.add_directive`への呼び出しは、per:ref: including_configurationとしてインクルードされることを意図した"frameworky "パッケージ内の `` includeme``関数内ではしばしば"隠されています" via:meth:〜pyramid.config.Configurator.include`。たとえば、このコードを `` pyramid_subscriberhelpers``というパッケージに入れた場合、

1
2
3
def includeme(config):
    config.add_directive('add_newrequest_subscriber',
                         add_newrequest_subscriber)

アドオンパッケージの `` pyramid_subscriberhelpers``のユーザーは、それをインストールして、次に実行できます:

1
2
3
4
5
6
7
def mysubscriber(event):
    print(event.request)

from pyramid.config import Configurator
config = Configurator()
config.include('pyramid_subscriberhelpers')
config.add_newrequest_subscriber(mysubscriber)

ディレクティブで `` config.action``を使う

カスタムディレクティブが既存のコンフィグレーターメソッド(上記のように:meth: pyramid.config.Configurator.add_subscriber`のような)に関して独占的にその作業を行うことができない場合、ディレクティブは:meth:`ピラミッド.config.Configurator.action`メソッド。このメソッドは、:meth: `pyramid.config.Configurator.commit`が呼び出されたときに、Pyramidが処理しようとする" actions "のリストにエントリを追加します。アクションとは:term: `discriminator、おそらくコールバック関数、そして恐らくピラミッドのアクションシステムによって使用される他のメタデータを含む辞書です。

"アクション"メソッドを使用するディレクティブの例を次に示します。

1
2
3
4
5
6
7
8
def add_jammyjam(config, jammyjam):
    def register():
        config.registry.jammyjam = jammyjam
    config.action('jammyjam', register)

if __name__ == '__main__':
    config = Configurator()
    config.add_directive('add_jammyjam', add_jammyjam)

ファンシーですが、それは何ですか?アクションメソッドはいくつかの引数を受け取ります。 `` add_jammyjam``という名前の上記のディレクティブでは、meth: 〜pyramid.config.Configurator.action`を2つの引数で呼び出します。文字列 jammyjam``が discriminator`という名前の最初の引数として渡され、 `` registerable``という名前のクロージャー関数は `` callable``という名前の第2引数として渡されます。

:meth: 〜pyramid.config.Configurator.action`メソッドが呼び出されると、保留中の設定アクションのリストにアクションが追加されます。同一のディスクリミネータ値を持つすべての保留中のアクションは潜在的に互いに衝突します(参照:ref: `conflict_detection)。コンフィグレータの:meth: 〜pyramid.config.Configurator.commit`メソッドが(明示的にまたは:meth:〜pyramid.config.Configurator.make_wsgi_app`を呼び出した結果として)呼び出されると、競合するアクションは自動的に可能性があります:ref: `automatic_conflict_resolution`に従って解決されます。競合を自動的に解決できない場合、a:exc: `pyramid.exceptions.ConfigurationConflictError`が発生し、アプリケーションの起動が妨げられます。

したがって、上記の例では、 `` add_jammyjam``ディレクティブの消費者がこれを行った場合、

config.add_jammyjam('first')
config.add_jammyjam('second')

上記の一連の呼び出しの結果、アクションリストがコミットされたとき、2つの呼び出しによって生成されたアクションの弁別子が直接衝突するため、ユーザーのアプリケーションは起動しません。自動的な競合解決は競合を解決できません( `` config.include``が含まれていないので)、ユーザは `` add_jammyjam``の呼び出しの間にintermediate:meth: `pyramid.config.Configurator.commit`呼び出しを渡さなかった連続するコールが相互に競合していないことを確認してください。

これは、アクションメソッドの識別子引数の目的を示しています。アクションの一意性制約を示すために使用されます。競合が自動的にまたは手動で解決されない限り、同じディスクリミネータを使用する2つのアクションは競合します。 discriminatorは任意のハッシュ可能なオブジェクトですが、一般的には文字列またはタプルです。 あなたは、ユーザーがあいまいな構成ステートメントを提供しないことを宣言的に保証するために弁別子を​​使用します。

しかし、 `` add_jammyjam``の消費者が、設定の競合が発生しないような方法でそれを使用したとしましょう。

config.add_jammyjam('first')

今、何が起きた? `` add_jammyjam``メソッドが呼び出されると、アクションが保留アクションリストに追加されます。保留中の設定アクションが:meth: 〜pyramid.config.Configurator.commit`の間に処理され、競合が発生しなければ、* callable *は:meth:〜pyramid.config.Configurator.actionの第2引数として提供されます`add_jammyjam``内の`メソッドは引数なしで呼び出されます。 `` add_jammyjam``の呼び出し可能な関数は、 `` register``クロージャ関数です。 `` config.registry.jammyjam``の値を、 `` add_jammyjam``関数の `` jammyjam``引数として渡した値に設定します。したがって、ユーザの指令の呼び出しの結果は、レジストリの `` jammyjam``属性を文字列 `` first``に設定します。 * callableは、矛盾の検出がその仕事をする機会があるまで、ディレクティブがユーザーの呼び出し結果を延期するためにディレクティブによって使用されます*。

:meth: 〜pyramid.config.Configurator.action`メソッドには、 args`、` kw`、` order`、` `introspectables``などの引数があります。

`` args``と `` kw``は値として存在し、渡された場合、 `` callable``関数がコールバックされたときに引数として使用されます。例えば、私たちの指令は以下のようにそれらを使用するかもしれません:

1
2
3
4
5
6
def add_jammyjam(config, jammyjam):
    def register(*arg, **kw):
        config.registry.jammyjam_args = arg
        config.registry.jammyjam_kw = kw
        config.registry.jammyjam = jammyjam
    config.action('jammyjam', register, args=('one',), kw={'two':'two'})

上記の例では、このディレクティブがアクションの生成に使用され、そのアクションがコミットされると、 `` config.registry.jammyjam_args``は ``( 'one'、 ````と `` config.registry .jammyjam_kw``は `` {'two': 'two'} ``に設定されます。 `` callable``がクロージャー関数の場合、 `` args``と `` kw``は正直なところあまり有用ではありません。ただし、クロージャを呼び出し可能として使用しない場合は便利です。

「注文」は原注管理メカニズムです。 `` order``はデフォルトで整数 `` 0``になります。他の任意の整数に設定することができます。オーダーを共有するすべてのアクションは、上位のオーダーを共有する他のアクションの前に呼び出されます。これにより、最初に実行される別のディレクティブの呼び出し可能な呼び出しに依存する呼び出し可能なロジックを持つディレクティブを書くことができます。たとえば、Pyramidの:meth: pyramid.config.Configurator.add_view`ディレクティブは、:meth: pyramid.config.Configurator.add_route`メソッドよりも上位のアクションを登録します。このため、 `` add_view``メソッドの呼び出し可能メソッドは、 `` route_name``が渡された場合、この名前のルートが `` add_route``によって既に登録されていると仮定し、そのようなルートがまだ登録されていない場合は、設定エラーです(存在しないルートに `` route_name``パラメータで名前を付けるビューは呼び出されません)。

バージョン 1.6 で変更: Pyramid 1.6以降、あるアクションが別のアクションを呼び出すことは可能です。詳細は、:ref: `ordering_actions`を参照してください。

最後に、 `` introspectables``はterm: `introspectable`オブジェクトのシーケンスです。イントロスペクティブのシーケンスを:meth: `〜pyramid.config.Configurator.action`メソッドに渡すことができます。これにより、Pyramidの設定イントロスペクションシステムを拡張することができます。

オーダーアクション

Pyramidではevery:term: action`は他のアクションとの相対的な順序付けを持っています。アクション内のロジックは、:meth: `pyramid.config.Configurator.commit`(これは自動的に:meth: pyramid.config.Configurator.make_wsgi_app`によって呼び出されます)の呼び出しまで延期されます。つまり、コミット時まで何も起こらないので、config.add_route( 'foo'、 '/ foo') ``の前に `` config.add_view(route_name = 'foo') `` ** ** before ** ``を呼び出すことができます。コミット・サイクル中に競合が解決され、アクションが順序付けられ実行されます。

デフォルトでは、Pyramidのほとんどのアクションは:const: pyramid.config.PHASE3_CONFIG`の order``を持っています。同じオーダー・レベル内のすべてのアクションは、呼び出された順に実行されます。これは、アクションが別のアクションの前または後に確実に実行されなければならない場合、この動作をさせるために ` order``を明示的に定義する必要があることを意味します。たとえば、ビューは定義されているルートに依存します。したがって、:meth: pyramid.config.Configurator.add_route`によって作成されるアクションは:const: pyramid.config.PHASE2_CONFIG`の `` order``を持ちます。

事前定義されたフェーズ

:const: pyramid.config.PHASE0_CONFIG

  • このフェーズは、Pyramidのコアディレクティブの前にアクションを実行したい開発者のために予約されています。

:const: pyramid.config.PHASE1_CONFIG

  • :meth: pyramid.config.Configurator.add_renderer
  • :meth: pyramid.config.Configurator.add_route_predicate
  • :meth: pyramid.config.Configurator.add_subscriber_predicate
  • :meth: pyramid.config.Configurator.add_view_predicate
  • :meth: pyramid.config.Configurator.add_view_deriver
  • :meth: pyramid.config.Configurator.override_asset
  • :meth: pyramid.config.Configurator.set_authorization_policy
  • :meth: pyramid.config.Configurator.set_default_csrf_options
  • :meth: pyramid.config.Configurator.set_default_permission
  • :meth: pyramid.config.Configurator.set_view_mapper

:const: pyramid.config.PHASE2_CONFIG

  • :meth: pyramid.config.Configurator.add_route
  • :meth: pyramid.config.Configurator.set_authentication_policy

:const: pyramid.config.PHASE3_CONFIG

  • 特に指定しない限り、すべての組み込みディレクティブまたはカスタムディレクティブのデフォルトです。

アクションからアクションを呼び出す

バージョン 1.6 で追加.

Pyramidのコンフィギュレータは、現在または後の `` order``フェーズに追加されている限り、コミットサイクル中にアクションを追加することを許可します。これは、カスタムアクションがコミット時まで決定を延期し、次に:meth: `pyramid.config.Configurator.add_route`のようなものを実行することを意味します。アドオンが複数の他のアクションを呼び出す必要がある場合は、より優れた競合検出を提供することもできます。

例えば、 `` add_route``と `` add_view``を呼び出すaddonを作ってみましょう。しかし、addonへの他の呼び出しと競合するようにしましょう:

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

def includeme(config):
    config.add_directive('add_auto_route', add_auto_route)

def add_auto_route(config, name, view):
    def register():
        config.add_view(route_name=name, view=view)
        config.add_route(name, '/' + name)
    config.action(('auto route', name), register, order=PHASE0_CONFIG)

他の誰かがあなたのアドオンを使用し、このルートと別のルートとの間に矛盾があるかどうか、あるいは `` add_auto_route``を2回呼び出すことができます。 ** ** `` add_view``または `` add_route``の前にアクション**を呼び出さなければならなかったことに注目してください。これを後で呼び出そうとすると、その後の `` add_view``と `` add_route``の呼び出しは、そのフェーズがすでに実行されているためにコンフリクトを引き起こし、コンフィギュレータはそのコミット時にビューを追加することができません。サイクル。

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

def main(global_config, **settings):
    config = Configurator()
    config.include('auto_route_addon')
    config.add_auto_route('foo', my_view)

def my_view(request):
    return request.response

構成イントロスペクションの追加

バージョン 1.3 で追加.

Pyramidは、デバッグツールで実行中のアプリケーションの構成を可視化するために使用できる構成イントロスペクションシステムを提供します。

すべての組み込みピラミッド指令(:meth: pyramid.config.Configurator.add_view`と:meth: pyramid.config.Configurator.add_route`)は、呼び出し時にイントロスペクタブルのセットを登録します。例えば、 `` add_view``を介してビューを登録すると、ディレクティブは少なくとも1つのイントロスペクタブルを登録します。ビューの登録自体についてイントロスペクトし、引き渡された引数に人間が消費可能な値を提供します。後でイントロスペクションクエリシステムを使用して、特定のビューがレンダラーを使用するかどうか、または特定のビューが特定のリクエストメソッドに限定されているかどうか、または特定のビューが登録されているルートを判断できます。 Pyramid "デバッグツールバー"は、イントロスペクションシステムをさまざまな方法で使用して、Pyramid開発者に情報を表示します。

イントロスペクション値は:term: introspectable`オブジェクトのシーケンスが:meth:〜pyramid.config.Configurator.action`メソッドに渡されるときに設定されます。イントロスペクタブルを使用するディレクティブの例を次に示します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def add_jammyjam(config, value):
    def register():
        config.registry.jammyjam = value
    intr = config.introspectable(category_name='jammyjams',
                                 discriminator='jammyjam',
                                 title='a jammyjam',
                                 type_name=None)
    intr['value'] = value
    config.action('jammyjam', register, introspectables=(intr,))

if __name__ == '__main__':
    config = Configurator()
    config.add_directive('add_jammyjam', add_jammyjam)

気づいた場合、上記のディレクティブはConfigurator(:attr: pyramid.config.Configurator.introspectable)の` `introspectable``属性を使用してイントロスペクティブオブジェクトを作成します。イントロスペクショナブルオブジェクトのコンストラクタには、少なくとも "category_name"、 "discriminator"、 "title"、および "type_name"の4つの引数が必要です。

`` category_name``は、このintrospectableの論理カテゴリを表す文字列です。通常、category_nameはアクションを介して追加されるオブジェクトの型の複数形です。

「弁別子」は**カテゴリ内の一意の値**です(アクション識別子の違いは、アクション全体で一意でなければなりません)。これは、通常、カテゴリ内のこのイントロスペクタブルに固有の値を表す文字列またはタプルです。これは、リンクを生成するため、および他のイントロスペクタブルのための関係形成ターゲットの一部として使用されます。

`` title``は、人間を消耗させる文字列であり、イントロスペクションシステムフロントエンドがこのイントロスペクトラブルのフレンドリな要約を示すために使用できます。

`` type_name``は、ソートやプレゼンテーションの目的で、このカテゴリの中でこのイントロスペクタブルをサブタイプ化するために使用できる値です。任意の値にすることができます。

イントロスペクターは辞書のようなものです。これは、関連する指令に渡される引数に通常関連する、キーと値のペアの任意のセットを含むことができます。 "category_name"、 "discriminator"、 "title"、および "type_name"はintrospectableに関する* metadata *ですが、キーと値のペアとして提供される値は、introspectableによって提供される実際のデータです。上記の例では、 `` value``キーをディレクティブに渡される `` value``引数の値に設定します。

上のディレクティブは、イントロスペクターブルを変更し、 `` introspectable``キーワード引数の値としてタプルの最初の要素として ``アクション ``メソッドに渡します。これは、このイントロスペクタブルをアクションに関連付けます。イントロスペクションツールは、このイントロスペクタブルをインデックスに表示します。

イントロスペクティブな関係

2人のイントロスペクターは、お互いの間に関係を持っているかもしれません。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
def add_jammyjam(config, value, template):
    def register():
        config.registry.jammyjam = (value, template)
    intr = config.introspectable(category_name='jammyjams',
                                 discriminator='jammyjam',
                                 title='a jammyjam',
                                 type_name=None)
    intr['value'] = value
    tmpl_intr = config.introspectable(category_name='jammyjam templates',
                                      discriminator=template,
                                      title=template,
                                      type_name=None)
    tmpl_intr['value'] = template
    intr.relate('jammyjam templates', template)
    config.action('jammyjam', register, introspectables=(intr, tmpl_intr))

if __name__ == '__main__':
    config = Configurator()
    config.add_directive('add_jammyjam', add_jammyjam)

上記の例では、 `` add_jammyjam``ディレクティブは2つのイントロスペクタブルを登録します。最初のものはディレクティブに渡される `` value``に関連し、2番目はディレクティブに渡される `` template``に関連します。ディレクティブ内のコンセプトがイントロスペクト可能なほど重要であると信じる場合は、同じディレクティブに複数のイントロスペクタブルを登録させ、1つのイントロスペクタブルを "メインアイデア"に登録し、もう1つを関連コンセプトに登録することができます。

上記の `` intr.relate``(:meth: pyramid.interfaces.IIntrospectable.relate)の呼び出しには、カテゴリ名とディレクティブという2つの引数が渡されます。上記の例は、 `` intr``イントロスペクターと `` tmpl_intr``イントロスペクターの間に関係を形成することを望んでいます。 `` relate``に渡される引数は `` tmpl_intr``のイントロスペクタブルのカテゴリ名と識別子です。

同じディレクティブで作成された2つのイントロスペクタブルの間で、関係を作成する必要はありません。代わりに、一方のディレクティブのカテゴリ名とディスクリミネータのどちらかで `` relate``を呼び出すことで、一方のディレクティブで作成されたイントロスペクタブルと別のディレクティブで作成されたもう一方のイントロスペクサブルとの間に関係を形成できます。ただし、イントロスペクターと存在しない別のイントロスペクターを関連付けると、構成コミット時にエラーが発生します。

イントロスペクション可能な関係は、イントロスペクション値のフロントエンドシステムレンダリングで表示されます。たとえば、ビュー登録がルート名の名前を付ける場合、コール可能ビューに関連するイントロスペクタブルは、それが関連するルートへの参照を示し、逆も同様です。