(機械翻訳) トラバーサルとURLディスパッチの組み合わせ¶
most:app: Pyramid`アプリケーションを書くと、term: resource location`サブシステム:トラバーサルまたはURLディスパッチのいずれかを使用できます。しかし、限られた一連の問題を解決するには、同じアプリケーション内でトラバーサルとURLの両方のディスパッチを併用すると便利です。 :app: `Pyramid`は*ハイブリッドアプリケーションを介してこれを可能にします。
警告
"ハイブリッド" URLディスパッチ+トラバースアプリケーションの動作について推論するのは難しいことです。 URLのディスパッチとトラバースを一緒に使うことを成功させるためには、URLパターンマッチング、ルートファクトリ、:term: `traversal`アルゴリズム、およびそれらの間の潜在的な相互作用を理解する必要があります。したがって、必要がない限りハイブリッド動作に依存するアプリケーションを作成することはお勧めしません。
非ハイブリッドアプリケーションのレビュー¶
:app: Pyramid`は、"デュアルモード"フレームワークです。このチュートリアルでは、term: URL dispatch` *または*のいずれかを使ってアプリケーションを作成する方法を説明しています。 :用語:トラバーサル。この章では、これらの2つのディスパッチメカニズムをどのように組み合わせるかについて詳しく説明しますが、それらを組み合わせようとする前に、どのように孤立して動作しているかを見ていきます。
URLディスパッチのみ¶
URLをコードにマップするために:term: `URL dispatch`を使用するアプリケーションは、アプリケーション開始構成内で次のようなステートメントを持つことがよくあります:
1 2 3 4 5 6 7 | # config is an instance of pyramid.config.Configurator
config.add_route('foobar', '{foo}/{bar}')
config.add_route('bazbuz', '{baz}/{buz}')
config.add_view('myproject.views.foobar', route_name='foobar')
config.add_view('myproject.views.bazbuz', route_name='bazbuz')
|
それぞれ:term: ルート`は、1つまたは複数のビュー呼び出し可能変数に対応します。呼び出し可能な各ビューは:meth: `〜pyramid.config.Configurator.add_view`への呼び出し中にその名前と一致する `route_name``パラメータを渡すことによってルートに関連付けられます。リクエスト中にルートがマッチした場合、:term: `view lookup`を使用して、関連するビューを呼び出し可能に照合します。 :meth: `〜pyramid.config.Configurator.add_route`への呼び出しは、アプリケーションがURLディスパッチを使用していることを示します。
トラバーサルのみ¶
トラバースのみを使用するアプリケーションでは、次のようなビュー構成宣言があります。
1 2 3 4 | # config is an instance of pyramid.config.Configurator
config.add_view('mypackage.views.foobar', name='foobar')
config.add_view('mypackage.views.bazbuz', name='bazbuz')
|
上記の設定をアプリケーションに適用すると、 `` / foobar``というURLにアクセスしたときに上で呼び出せる `` mypackage.views.foobar``ビューが呼び出されます。同様に、 `` mypackage.views.bazbuz``というビューは `` / bazbuz``というURLが訪れると呼び出されます。
通常、トラバーサルを排他的に使用するアプリケーションは、起動コードに:meth: `pyramid.config.Configurator.add_route`を呼び出すことはありません。
ハイブリッドアプリケーション¶
トラバーサルまたはURLディスパッチだけで、:app: `Pyramid`アプリケーションを作成することができます。ただし、アプリケーションを構築するときに、トラバーサルとURLディスパッチのコンセプトを組み合わせることも可能で、その結果はハイブリッドアプリケーションになります。ハイブリッドアプリケーションでは、特定のルートが一致した後にトラバーサルが実行されます。
ハイブリッドアプリケーションは、"純粋な"トラバーサルベースのアプリケーションに似ていますが、"純粋な" URLディスパッチベースのアプリケーションと似ています。しかし、「純粋な」トラバーサルベースのアプリケーションとは異なり、ハイブリッドアプリケーションでは、「トラバーサル」は、ルートが既に一致した後にリクエスト中に実行されます。これは、ルートの `` pattern``引数を表すURLパターンがリクエストの `` PATH_INFO``と一致しなければならないことを意味し、ルートパターンがマッチした後、"通常:term: resource location`と:term: view lookup`が適用されます。
純粋にトラバーサルベースのアプリケーションとハイブリッドアプリケーションの間には、4つの大きな違いがあります。
- 純粋にトラバーサルベースのアプリケーションでは、経路は定義されていません。ハイブリッドアプリケーションでは、少なくとも1つのルートが定義されます。
- 完全にトラバーサルベースのアプリケーションでは、使用されるルートオブジェクトはグローバルであり、起動時に提供される:term: `ルートファクトリ 'によって暗示されます。ハイブリッドアプリケーションでは、トラバーサルが始まる:term: `ルート`オブジェクトは、ルートごとに変化する可能性があります。
- 純粋にトラバーサルベースのアプリケーションでは、基礎となる:term: WSGI`環境の PATH_INFO``がトラバーサルパスとして卸売されています。ハイブリッドアプリケーションでは、トラバーサルパスは ` PATH_INFO``文字列全体ではなく、一致したルート設定のパターンで一致するパターンによって決定されたURLの一部です。
- 純粋にトラバーサルベースのアプリケーションでは、 `` route_name``引数に言及していないビュー設定は:term: view lookup`の間に考慮されます。ハイブリッドアプリケーションでは、ルートが一致すると、そのルートの名前を ` route_name``として記述するビュー設定だけが:term: `view lookup`の間に考慮されます。
より一般的には、ハイブリッドアプリケーション*は以下を除くトラバーサルベースのアプリケーションです。
- traversal * root *は、アプリケーションの起動時に提供される `` root_factory``からではなく、一致したルートのルート設定に基づいて選択されます。
- traversal * path *はリクエストの `` PATH_INFO``ではなく、マッチしたルートのルート設定に基づいて選択されます。
- ルートが一致したときにterm: view lookup`の間に選択されるビューのセットは、その設定において、マッチしたルートの name``と同じである `route_name``を特に指定するものに限定されます。
ハイブリッドモードアプリケーションを作成するには、特定の:term: ルートファクトリ 'を意味する:term:`ルート設定 `を使用し、特殊な動的部分を含む pattern``引数も含みます: * traverse ``または ` * subpath``を使用します。
ルートマッチのルートオブジェクト¶
ハイブリッドアプリケーションとは、ルートが一致した後、要求中にトラバーサルが実行されることを意味します。トラバーサルは定義上、常にルートオブジェクトから始まる必要があります。したがって、ルートがマッチした後、どのルートオブジェクトがトラバースされるかを知ることが重要です。
term: `ルート`オブジェクトが特定のルートマッチからどのような結果を出すのかは簡単です。経路が一致した場合:
- ルートの設定が:term: ルートファクトリー`を指す ` factory``引数を持つ場合、そのcallableは:term: `ルート`オブジェクトを生成するために呼び出されます。
- ルートの設定に `` factory``引数がない場合、:global::term: ルートファクトリ`が呼び出されて:term: `ルート`オブジェクトが生成されます。グローバルルートファクトリは、アプリケーションの起動時に:class: `〜pyramid.config.Configurator`に渡される `root_factory``引数によって暗示される呼び出し可能です。
- 起動時に `` root_factory``引数が:class: `〜pyramid.config.Configurator`に与えられない場合、* default *ルートファクトリが使用されます。デフォルトルートファクトリは、ルートオブジェクトを生成するために使用されます。
ルートパターンで `` * traverse``を使う¶
ハイブリッドアプリケーションは、ルートのパターンの終わりに特別なトークン `` * traverse``を含むルート設定を含めることを最も頻繁に意味します:
1 | config.add_route('home', '{foo}/{bar}/*traverse')
|
ルートの構成におけるパターンの最後にある `` * traverse``トークンは"remainder " * capture *値を意味します。これを使用すると、URLのパスセグメントの残りの部分と一致します。この残りは、トラバーサルを実行するために使用されるパスになります。
注釈
`` * remainder``のルートパターンの構文についてはref: `route_pattern_syntax`で詳しく説明しています。
ハイブリッドモードのアプリケーションは、term: traversal`を行うためにもっと重く依存します:term: resource location`と:term: view lookup`ほとんどの例は:ref: urldispatch_chapter`を示します。
上記のルートのパターンは `` * traverse`で終わるので、リクエスト中にこのルート設定が一致すると、:app: Pyramid`は:term: traversal`を:term: root`に対して使用しようとします。 :term: `ルートファクト`によって暗示されたオブジェクトで、ルートの設定によって暗示されています。このルートには ` root_factory``引数は明示的に指定されていないので、アプリケーションの*グローバル*ルートファクトリーか* default *ルートファクトリーのいずれかになります。一度:term: traversal`がa:term: context`リソースを見つけました:term: `view lookup`は"純粋な "トラバーサルベースのアプリケーションで呼び出されたのとほぼ同じ方法で呼び出されます。
このアプリケーションでは* global::term: ルートファクトリ 'が設定されていないと仮定しましょう。 * default *:term: `ルートファクトリ`はトラバースできません。有用な ` __getitem__``メソッドはありません。したがって、便利なハイブリッドアプリケーションを作成するために、このルート構成をカスタムルートファクトリに関連付ける必要があります。そのために、 `` routes.py``という名前のモジュールのように見えるルートファクトリを作成したとしましょう:
1 2 3 4 5 6 7 8 9 10 11 12 13 | class Resource(object):
def __init__(self, subobjects):
self.subobjects = subobjects
def __getitem__(self, name):
return self.subobjects[name]
root = Resource(
{'a': Resource({'b': Resource({'c': Resource({})})})}
)
def root_factory(request):
return root
|
上では、横断可能な(偽の)リソースツリーと、特定のルート設定ステートメントの一部として使用できる `` root_factory``関数を定義しています。
1 2 | config.add_route('home', '{foo}/{bar}/*traverse',
factory='mypackage.routes.root_factory')
|
上記の `` factory``は、定義した関数を指しています。 `` Resource``クラスのインスタンスをこのルートが一致するたびにルートオブジェクトとして返します。 `` Resource``クラスのインスタンスは、名目上有用な何かを行う `` __getitem__``メソッドを持っているので、ツリートラバーサルに使うことができます。トラバーサルはリソースツリーのリソースを歩くために `` __getitem__``を使うので、ルートステートメントが意味するルートリソースに対してトラバーサルを使うのは合理的なことです。
注釈
`` root_factory``関数を:class: 〜pyramid.config.Configurator`コンストラクタの root_factory``引数として、ルートの設定内の特定のルートに関連付けるのではなく、それを使用することもできました。マッチするが、 ` factory``属性に名前をつけないハイブリッドルート設定は、グローバルな `` root_factory``関数を使ってルートオブジェクトを生成します。
上記の `` home``という名前のルート設定がリクエスト中にマッチすると、生成されたmatchdictはパターン `` {foo} / {bar} / * traverse``に基づいています。パターン内の `` * traverse``要素が意味する"キャプチャ値"は、ルートファクトリから返されたルートオブジェクトから開始して、コンテキストリソースを見つけるためにリソースツリーを走査するために使用されます。上の例では、:term: ルート`オブジェクトは ` routes.py``の `` root``というインスタンスになります。
パターン `` {foo} / {bar} / * traverse`を持つルートに一致したURLが `` http:// example.com / one / two / a / b / c``である場合、トラバーサルパスルートオブジェクトに対して `` a / b / c``が使用されます。その結果、:app: Pyramid`は、ルートオブジェクトから始まり、 'a'`、` b'`、および` `c'``をたどることを試みます。
上記の例では、この特定のトラバーサルステップのセットは、ビューの:term: context`リソースが、私たちの偽のリソースツリーで 'c'``という名前の `Resource``オブジェクトであることを意味します、トラバーサルの結果である:term: `view name`は空文字列になります。なぜこの結果が推測されるのかを見直す必要がある場合は、:ref: `traversal_algorithm`を参照してください。
この時点で、適切なview呼び出し可能なものが見つけられ、:term: view lookup:ref:` view_configuration`で説明されているように呼び出されますが、注意が必要です:ビューの参照が機能するためには、 when:term: `view lookup`が、ルートがマッチした後に呼び出されるときにマッチする設定です:
1 2 3 | config.add_route('home', '{foo}/{bar}/*traverse',
factory='mypackage.routes.root_factory')
config.add_view('mypackage.views.myview', route_name='home')
|
上記の:meth: 〜pyramid.config.Configurator.add_view`の呼び出しには route_name``引数が含まれています。 ` route_name``引数を含むビュー設定は、特定のビュー宣言をルートと関連付けて、ルートが*と一致したときだけビューを呼び出さなければならないことを示すためのものです。
:meth: 〜pyramid.config.Configurator.add_view`は、既存のルートの name``引数の値を参照する route_name``属性を渡すことができます。上の例では、ルート名は ` home``であり、上に定義されたルートの名前を参照しています。
上記の `` mypackage.views.myview``ビューは以下の条件が満たされたとき呼び出されます:
- "home "という名前のルートが一致しています。
- :term:トラバーサルの結果である `view name`は空文字列です。
- :term: `context`リソースは任意のオブジェクトです。
ハイブリッドルートが一致したときに呼び出される代替ビューを宣言することもできます。
1 2 3 4 5 | config.add_route('home', '{foo}/{bar}/*traverse',
factory='mypackage.routes.root_factory')
config.add_view('mypackage.views.myview', route_name='home')
config.add_view('mypackage.views.another_view', route_name='home',
name='another')
|
上記の `` mypackage.views.another_view``の `` add_view``呼び出しは、異なるビューと、もっと重要なことに、異なる:term: view name`という名前を付けます。上記の ` mypackage.views.another_view``ビューは、以下の条件が満たされたときに呼び出されます:
- "home "という名前のルートが一致しています。
- :term: view name`は `another``です。
- :term: `context`リソースは任意のオブジェクトです。
例えば、前述のリソースツリーを使用するアプリケーションに `` http:// example.com / one / two / a / another``というURLが提供されている場合、 `` mypackage.views.another_view``ビューは呼び出し可能です:term: view name`は空文字列の代わりに another``となるので、 `mypackage.views.myview``ビューの代わりに呼び出すことができます。
より複雑なマッチングを構成することができます。 * route 設定ステートメントと view *設定ステートメントのすべての引数は、ハイブリッドアプリケーションでサポートされています(term: `述語`引数など)。
ルート定義における `` traverse``引数の使用¶
パターンに `` * traverse``の余りマーカーを使うのではなく、:meth: 〜pyramid.config.Configurator.add_route`メソッドの `traverse``引数を使うことができます。
`` * traverse``の余りマーカーを使うと、トラバーサルパスは、ルートが一致したときのリクエストURLの残りのセグメントに限定されます。しかし、 `` traverse``引数や属性を使うと、トラバーサルパスをどのように構成するかをもっと制御できます。
以下は、:meth: 〜pyramid.config.Configurator.add_route`の呼び出しにおける `traverse``パターンの使用方法です:
1 2 | config.add_route('abc', '/articles/{article}/edit',
traverse='/{article}')
|
`` traverse`引数の構文は `` pattern``の構文と同じです。
上記のように `` / articles / {article} / edit``が提供され、 `` traverse``引数が `` / {article} である場合、リクエストが来たら
article``の一致値が `` 1``(リクエストURIが `` / articles / 1 / edit``のとき)にルートが一致するようにするために、トラバーサルパスは次のように生成されます。 `` / 1``です。つまり、ルートオブジェクトの `` __getitem__``はトラバーサルフェーズ中に名前が `` 1``で呼び出されます。 `` 1``オブジェクトが存在する場合、要求の:term: `context`になります。 :ref: `traversal_chapter`の章には、トラバースに関する詳細があります。
トラバーサルパスにパターン引数に存在しないセグメントマーカー名が含まれていると、実行時エラーが発生します。 `` traverse``パターンは `` path``に存在しないセグメントマーカーを含んではいけません。
`` traverse``引数はパターンに `` * traverse``残余マーカがあるルートにアタッチされているときは無視されることに注意してください。
トラバーサルは、このルートが意味するルートオブジェクト(グローバルルートまたはこのルートに関連付けられた `` factory``によって返されるオブジェクト)から始まります。
グローバルビューを一致させる¶
デフォルトでは、パターンに `` * traverse``があるルートが一致したときに、ビュールックアップ中に `` route_name``を記述したビュー設定だけが見付かります。ルート定義に `` use_global_views``フラグを追加することで、ルートと一致する `` route_name``属性のないビューを許可することができます。たとえば、以下の `` abc``という名前のルートがマッチし、 `` / abc / bazbuz``が `` PATH_INFO``である場合、 `` myproject.views.bazbuz``のビューが見つかります。 view構成ステートメントに `` route_name = "abc " ``属性がありません。
1 2 | config.add_route('abc', '/abc/*traverse', use_global_views=True)
config.add_view('myproject.views.bazbuz', name='bazbuz')
|
ルートパターンで `` * subpath``を使う¶
トラバースに影響を与えたいという非常にまれなケースがあります:term: subpath`ルートが実際にトラバーサルを実行せずにマッチするときです。たとえば、:func: `pyramid.wsgi.wsgiapp2`デコレータと:class: pyramid.static.static_view`ヘルパーは、 `` use_subpath``引数が `` use_subpath``のときに要求のサブパスから `` PATH_INFO``を計算しようとします。 `True``なので、この値に影響を与えることは有益です。
`` * subpath``がパターン内に存在する場合、パスは実際にはトラバースされませんが、トラバーサルアルゴリズムは `` * subpath``のキャプチャ値が暗示する:term: `subpath`リストを返します。ルートの宣言では、このようなパターンが最も一般的です。
1 2 3 4 5 6 | from pyramid.static import static_view
www = static_view('mypackage:static', use_subpath=True)
config.add_route('static', '/static/*subpath')
config.add_view(www, route_name='static')
|
`` mypackage.views.www``は、class: `pyramid.static.static_view`のインスタンスです。これにより、静的ヘルパーは、サブパス内のすべてをファイル名としてトラバースするように効果的に指示します。
ハイブリッドURLの生成¶
バージョン 1.5 で追加.
:meth: pyramid.request.Request.resource_url`メソッドと:meth: pyramid.request.Request.resource_path`メソッドは、トラバーサルリソースへのパスを含むルートプレフィックス付きURLを生成しやすくするオプションのキーワード引数を受け入れます: `` route_name``、 `` route_kw``、および `` route_remainder_name``です。
`` * remainder``パターン( `` * traverse``、 `` * subpath``、 `` * fred``などの任意の残りのパターン)を含むパターンを持つルートは、 `` request.resource_url(...、route_name =) ``と `` request.resource_path(...、route_name =) ``のターゲット名です。
たとえば、Pyramidアプリケーションで定義されているルートが次のようになっているとします。
config.add_route('mysection', '/mysection*traverse')
`` http:// example.com / mysection / a / というURLを生成したい場合、下記の変数 `` a``が以下のリソースを指していると仮定すると、ルートの子で `` __name__``の `` a
:
request.resource_url(a, route_name='mysection')
パス部分 `` / mysection / a / ``のみを生成することができます。
request.resource_path(a, route_name='mysection')
パスは仮想ホストを認識しているので、 `` X-Vhm-Root``環境変数がリクエストに存在し、 `` / a``に設定されている場合、上記の `` request.resource_url``の呼び出しは`` http:// example.com / mysection / ``を生成し、上記の `` request.resource_path``の呼び出しは `` / mysection / ``を生成します。詳細は、:ref: `virtual_root_support`を参照してください。
使用しようとしているルートが簡単な動的パーツの値を入力してURLを生成する必要がある場合は、これらを `` resource_url``と `` resource_path``の `` route_kw``引数として渡すことができます。たとえば、ルート定義が次のようになっていると仮定します。
config.add_route('mysection', '/{id}/mysection*traverse')
上記の `` {id} ``を記入するために `` route_kw``を渡すことができます:
request.resource_url(a, route_name='mysection', route_kw={'id':'1'})
`` route_kw``を渡しても `` route_name``を渡さなければ、 `` route_kw``は無視されます。
デフォルトでは、この機能は、フードの下で `` route_url``を呼び出し、リソースパスの値を `` traverse``としてその関数に渡すことによって機能します。あなたのルートに `` * starpath``などの別の `` * stararg``残余名がある場合、 `` resource_url``や `` resource_path``に `` traverse``の代わりに `` traverse``を使用するように伝えることができます`` route_remainder_name``を渡します。たとえば、次のルートがあるとします。
config.add_route('mysection', '/mysection*subpath')
以下のようにして `` resource_url``を使って `` * subpath``の値を入力することができます:
request.resource_path(a, route_name='mysection',
route_remainder_name='subpath')
`` route_remainder_name``を渡しても `` route_name``を渡さなければ、 `` route_remainder_name``は無視されます。
`` route_name``引数が残りのstarargを持たないルートを指しているときに `` resource_path``または `` resource_url``を使用しようとすると、エラーは発生しませんが、生成されたURLには含まれません残りのいずれかの情報。
通常、 `` resource_path``と `` resource_url``( `` query``、 `` anchor``、 `` host``、 `` port``、および位置要素など)に渡される他のすべての値は、この構成で期待どおりに動作します。
この機能はリソースオブジェクトに実装された `` __resource_url__``機能(:ref: overriding_resource_url_generation`参照)と互換性がないことに注意してください。あなたのリソースによって提供される ` __resource_url__``は `` route_name``を渡すと無視されます。