(機械翻訳) サブリクエストの呼び出し

バージョン 1.4 で追加.

:app: Pyramid`では、リクエストの処理中に任意の時点でサブリクエストを呼び出すことができます。サブリクエストを呼び出すと、同じアプリケーション内で呼び出し可能な別のビューを実行しているときに:app: `Pyramid`アプリケーション内で呼び出し可能なビューから:term: response`オブジェクトを取得できます。

サブリクエストを使用するアプリケーションの例を次に示します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.request import Request

def view_one(request):
    subreq = Request.blank('/view_two')
    response = request.invoke_subrequest(subreq)
    return response

def view_two(request):
    request.response.body = 'This came from view_two'
    return request.response

if __name__ == '__main__':
    config = Configurator()
    config.add_route('one', '/view_one')
    config.add_route('two', '/view_two')
    config.add_view(view_one, route_name='one')
    config.add_view(view_two, route_name='two')
    app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 8080, app)
    server.serve_forever()

`` / view_one``がブラウザに表示されているとき、ブラウザペインに表示されるテキストは これはview_two``から来ました。 `` view_one``ビューは: `` meth: `pyramid.request.Request.invoke_subrequest` APIを使って、同じアプリケーション内で別のビュー(` `view_two)から応答を取得しました。 `` view_two``ビューの登録にマッチすると知っていたURLを持った新しいリクエストを作成し、その新しいリクエストを:meth: pyramid.request.Request.invoke_subrequest`に渡すことでそうしました。 ` view_two``ビューのcallableが呼び出され、レスポンスが返されました。 `` view_one``ビューは `` view_two``ビューから取得したレスポンスを単に呼び出し可能にしました。

サブリクエストを介して呼び出されたビューが実際に*リテラル*レスポンスオブジェクトを返すかどうかは関係ありません。レンダラーを使用する呼び出し可能ビュー、または:meth: `pyramid.request.Request.invoke_subrequest`で見つけられ起動されたときに応答アダプタによって解釈されるオブジェクトを返すビューは、Responseオブジェクトを返します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.request import Request

def view_one(request):
    subreq = Request.blank('/view_two')
    response = request.invoke_subrequest(subreq)
    return response

def view_two(request):
    return 'This came from view_two'

if __name__ == '__main__':
    config = Configurator()
    config.add_route('one', '/view_one')
    config.add_route('two', '/view_two')
    config.add_view(view_one, route_name='one')
    config.add_view(view_two, route_name='two', renderer='string')
    app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 8080, app)
    server.serve_forever()

`` view_two``ビューのcallableは文字列を返しましたが、見つかったビュー登録に関連付けられた `` string``レンダラーがそれを消費のための"実際の"応答オブジェクトに変換するように呼び出されました「view_one」によって。

間接的に呼び出し可能なビューを呼び出すことによって無条件に応答オブジェクトを取得できることは、単純にビュー呼び出し可能オブジェクトをインポートして直接実行するのではなく、meth: `pyramid.request.Request.invoke_subrequest`を使用する主な利点です。呼び出し可能なビューを直接呼び出すことができれば、サブリクエストを使ってビューを呼び出すことはあまり利点がないことに注意してください。サブリクエストは遅く、ビュー呼び出し可能な関数で返されるリテラル情報だけが実際に必要な場合はあまり便利ではありません。

デフォルトで、サブリクエストによって呼び出されたビュー呼び出し可能呼び出しが例外を発生させた場合、:term: 例外があっても:meth:〜pyramid.request.Request.invoke_subrequest`の呼び出し側に例外が発生することに注意してくださいビュー構成:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.request import Request

def view_one(request):
    subreq = Request.blank('/view_two')
    response = request.invoke_subrequest(subreq)
    return response

def view_two(request):
    raise ValueError('foo')

def excview(request):
    request.response.body = b'An exception was raised'
    request.response.status_int = 500
    return request.response

if __name__ == '__main__':
    config = Configurator()
    config.add_route('one', '/view_one')
    config.add_route('two', '/view_two')
    config.add_view(view_one, route_name='one')
    config.add_view(view_two, route_name='two', renderer='string')
    config.add_view(excview, context=Exception)
    app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 8080, app)
    server.serve_forever()

上記のコードを実行してブラウザで `` / view_one``を訪れると、 `` excview``:term: exception view`が実行されません。代わりに:meth: `〜pyramid.request.Request.invoke_subrequest`を呼び出すと、:exc: ValueError`例外が発生し、応答が生成されません。私たちはこの行動を変えることができます。その方法については、 `` use_tweens``引数の議論で後述します。

トゥイーンのサブリクエスト

:meth: pyramid.request.Request.invoke_subrequest APIは、必須の位置引数` request``と省略可能なキーワード引数 use_tweens``をデフォルトで `False``の2つの引数を受け取ります。

APIに渡される `` request``オブジェクトはPyramidリクエストインタフェース(:class: pyramid.request.Request`インスタンスなど)を実装するオブジェクトでなければなりません。 ` use_tweens``が `` True``の場合、要求は要求入力に最も近いtweenスタックの:term: tween`に送られます。 ` use_tweens``が `` False``の場合、リクエストはメインルータハンドラに送られ、トゥイーンは呼び出されません。

上の例では、:meth: 〜pyramid.request.Request.invoke_subrequest`の呼び出しは常に例外を発生させます。これは ` use_tweens``のデフォルト値を使用しているためです。これは `` False``です。代わりに、 `` use_tweens = True``を渡して、例外を発生させる代わりに:term: exception view`が設定されている場合に、例外をResponseに変換するようにすることもできます。これは、ビューが例外を発生させると、:ref: `exception_views`で説明されているように、例外ビュー:term: tween`によって例外ビューが呼び出されるからです。

`` use_tweens = True``を:meth: `〜pyramid.request.Request.invoke_subrequest`の呼び出しに渡すことで、以下のようにして、サブリクエストをトゥイーンスタックを介して実行させることができます:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.request import Request

def view_one(request):
    subreq = Request.blank('/view_two')
    response = request.invoke_subrequest(subreq, use_tweens=True)
    return response

def view_two(request):
    raise ValueError('foo')

def excview(request):
    request.response.body = b'An exception was raised'
    request.response.status_int = 500
    return request.response

if __name__ == '__main__':
    config = Configurator()
    config.add_route('one', '/view_one')
    config.add_route('two', '/view_two')
    config.add_view(view_one, route_name='one')
    config.add_view(view_two, route_name='two', renderer='string')
    config.add_view(excview, context=Exception)
    app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 8080, app)
    server.serve_forever()

上記の場合、 `` request.invoke_subrequest(subreq) ``の呼び出しは例外を発生させません。代わりに、応答を生成するために例外ビューを呼び出すトゥイーンが実行され、したがって `` excview``が実行されるため、 `` view_two``の呼び出しを試行して"500 "応答を取得します。

これは:meth: 〜pyramid.request.Request.invoke_subrequest`に対して use_tweens = True``と use_tweens = False``引数を指定することの大きな違いの1つです。 ` use_tweens = True``は、 `` pyramid_debugtoolbar`を持っていればデバッグHTMLを注入して、tweenリストに `` pyramid_tm``を持っていれば、サブリクエストで実行されたロジックのコミットまたはアボートを呼び出すことを意味するかもしれません。 Tweenリストとその他の特定のトゥイーン関連の副作用で定義されています。

:meth: `〜pyramid.request.Request.invoke_subrequest`関数は、無条件に以下を行います:

  • スレッドローカルスタックを管理して、func: 〜pyramid.threadlocal.get_current_request`と:func:〜pyramid.threadlocal.get_current_registry`はリクエスト中に動作します(元のリクエストの代わりにサブリクエストを返します)。
  • それは、それが渡される要求オブジェクトに `` registry``属性と `` invoke_subrequest``属性(呼び出し可能)を追加します。
  • これは、 `` request``として渡されたサブリクエストオブジェクトに対して、リクエスト拡張子(:meth: 〜pyramid.config.Configurator.add_request_method`または:meth:〜pyramid.config.Configurator.set_request_property`)を設定します。
  • これはリクエスト処理の開始時にa:class: `〜pyramid.events.NewRequest`イベントが送られるようにします。
  • コンテキストリソースが見つかった場合、a:class: `〜pyramid.events.ContextFound`イベントが送信されます。
  • これは、渡された要求によって暗示されたユーザーが、呼び出し前に呼び出し可能なビューを呼び出すために必要な許可を持っていることを保証します。
  • Pyramidアプリケーションから応答が得られた場合、サブリクエストの有効期間内に定義されたany:term: `response callback`関数を呼び出します。
  • レスポンスが得られた場合には:class: `〜pyramid.events.NewResponse`イベントが送られます。
  • サブリクエストの存続期間内に定義されたany:term: `finished callback`関数を呼び出します。

サブリクエストの呼び出しは、 `` use_tweens = True``のときに、Webクライアントから:app: Pyramid`ルータが受け取ったリクエストの呼び出しとほぼ同じです。 ` use_tweens = False``のとき、トゥイーンはスキップされますが、他のすべてのステップが実行されます。

元の `` request``オブジェクトを:meth: `〜pyramid.request.Request.invoke_subrequest`の引数として使うのは良い考えではありません。代わりに:meth: `pyramid.request.Request.blank`を使用して、上記の例に示すように新しいリクエストを作成する必要があります。リクエストオブジェクトを作成したら、サブリクエスト中に実行したいビュー呼び出し可能なものにマッサージする必要があります。これは、サブリクエストのURL、そのヘッダー、要求メソッド、およびその他の属性を調整することによって実行できます。 :class: `pyramid.request.Request`のドキュメンテーションは、呼び出すべきメソッドと作成するリクエストに設定する属性を公開し、次にそれを実際にあなたが呼び出すビューに一致させるものにマッサージしますサブリクエスト。

ビュー呼び出し可能な内部からのサブリクエストの使用を実証しましたが、トゥイーンまたはイベントハンドラ内で:meth: 〜pyramid.request.Request.invoke_subrequest APIを使用することもできます。あなたがそれを行うことはできますが、tweensは既に、定義上、サブリクエストを引き起こす関数へのアクセス権を持っているので、tween内からmeth: 〜pyramid.request.Request.invoke_subrequest`を呼び出すのは、 ` handle``関数に渡されます)。ただし、イベントハンドラ内で:meth: `〜pyramid.request.Request.invoke_subrequest`を呼び出すことはできます。

例外ビューの呼び出し

バージョン 1.7 で追加.

:app: Pyramid`アプリは以下を定義します:term:`例外ビュー<exception view>これは、要求を処理している間にコードから逃げ出した例外を処理できます。デフォルトでは、未処理の例外は ` EXCVIEW``:term: `tween`によって捕捉され、例外タイプを処理して適切なエラー応答を生成する例外ビューを検索します。

In:app: Pyramid 1.7:meth:` pyramid.request.Request.invoke_exception_view`が導入されました。これにより、ユーザーは手動で例外を処理しながら例外ビューを呼び出すことができます。これは、いくつかの異なる状況で役に立ちます:

  • 現在の呼び出しスタックまたはフローを失う例外を手動で処理する。
  • `` EXCVIEW``トゥイーンのコンテキスト外での例外処理。トゥイーンはリクエスト処理パイプラインの特定の部分だけをカバーします(参照:ref: router_chapter)。また、ミドルウェアに泡立つ可能性のある例外が発生する可能性のあるコーナーケースもあります。また、ウェブサーバーにはおそらく一般的な「500 Internal Server Error」がクライアントに返されます。

以下は、meth: `pyramid.request.Request.invoke_exception_view`の使用例です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def foo(request):
    try:
        some_func_that_errors()
        return response
    except Exception:
        response = request.invoke_exception_view()
        if response is not None:
            return response
        else:
            # there is no exception view for this exception, simply
            # re-raise and let someone else handle it
            raise

ほとんどの場合、このようなコードを書く必要はなく、 `` EXCVIEW``トゥイーンを使ってこれを処理することができます。