(機械翻訳) アドバンス:app: `Pyramid`デザインの特徴

:app: `Pyramid`は、他のフレームワークが抱える問題を避けるために、最初からビルドされています。

あなたはシングルトンを必要としません

同じDjangoアプリケーションを複数インストールするためにDjangoの `` settings.py``ファイルをパラメータ化することに苦労しましたか?あなたのユースケースに対して適切に動作するようにするためにフレームワークフィクスチャを猿パッチする必要がありましたか?非同期サーバーを使用してアプリケーションをデプロイしようとしたが、失敗しましたか?

これらの問題はすべて、term: mutable:term:` global state`という現象です。term: import time:term:`副作用 `sとterm ::`シングルトンのデータ構造。

:app: `Pyramid`はあなたがこの種の問題に遭遇しないように書かれています。単一のPythonプロセス内で異なって設定された*同じ*:app: `Pyramid`アプリケーションの複数のコピーを実行することさえ可能です。これにより共有ホスティング環境でのapp: `Pyramid`の実行が簡単になります。

述語でビューコードを簡略化する

ビューコードのロジックが次のようなもので始まって何回目になったのですか?

1
2
3
4
if request.user.is_authenticated:
    # do one thing
else:
    # do something else

他の多くのシステムとは異なり、:app: Pyramid`では、複数のビューを単一のルートに関連付けることができます。たとえば、 ` / items``というパターンでルートを作成することができます。ルートが一致すると、リクエストメソッドがGETの場合は1つのビューに、リクエストメソッドがPOSTの場合は別のビューに、に。

:app: Pyramid`は:term: view predicate`のシステムを使ってこれを許可します。リクエストメソッドのマッチングは、:term: `view predicate`を使ってできる基本的なものです。また、クエリ文字列の要素、Acceptヘッダー、AJAX(XHR)要求かどうかなどの他の要求パラメーターとビューを関連付けることもできます。

上記の例では、代わりにこれを行うことができます:

1
2
3
4
5
6
7
@view_config(route_name="items", effective_principals=pyramid.security.Authenticated)
def auth_view(request):
    # do one thing

@view_config(route_name="items")
def anon_view(request):
    # do something else

このアプローチでは、よりシンプルでわかりやすく、より直接的にテスト可能なビューコードを開発できます。

参考

参照:ref: `view_configuration_parameters`を参照してください。

トランザクションについて心配しないでください

:app: Pyramid ':term:` cookiecutter` *はトランザクション管理システムを含むプロジェクトをレンダリングします。このシステムを使うと、いつ変更をコミットするのか心配することなく、app: `Pyramid`がそれを処理します。システムは要求の終わりにコミットするか、例外があった場合に中止します。

なぜそれは良いことですか?パーシスタンス層に手動で変更をコミットする状況を想像してみてください。変更が行われた後、他のフレームワークコードが*実行される可能性は非常に高いです。他のコードでエラーが発生した場合は、慎重ではない場合でも、一貫性のないデータで容易に解決できます。

トランザクション管理を使用すると、これについて考える必要がなくなります。要求が正常に完了し、すべての変更がコミットされるか、変更されず、すべての変更がアボートされます。

:app: Pyramid のトランザクション管理は拡張可能であるため、複数のデータベースまたは異なる種類のデータベース間でコミットを同期することができます。また、トランザクションがコミットされた場合に条件付きで電子メールを送信するなど、静的に保つなどの作業を行うこともできます。

参考

参照:ref: `bfg_sql_wiki_tutorial`(アプリケーションコードのどこにでもコミットステートメントがないことに注意してください)。

設定について心配しないでください

システムが小さくても、それをあなたの頭の中にすべて保持するのはかなり簡単です。しかし、システムが大きくなるにつれて、構成はより複雑になります。あなたのアプリは、数百から数千もの構成文を持つようになります。

:app: Pyramid の設定システムはそれぞれの文を追跡します。間違って2つの同じものを追加した場合、または:app: `Pyramid`は、両方のステートメントを同時にアクティブにすることを意味しないので、起動時に大声で苦情を言います。

:app: Pyramid の設定システムは愚かではありません。 :meth: `〜pyramid.config.Configurator.include`システムを使うと、自動的にそれ自身のコンフリクトを解決することができます。より多くのローカルステートメントはローカルステートメントよりも優先されます。したがって、大きなシステムを小さなシステムにインテリジェントに組み込むことができます。

参考

参照:ref: `conflict_detection`も参照してください。

シンプルな部品から強力なアプリケーションを作成する

:app: Pyramid`構造化:meth:〜pyramid.config.Configurator.include`メカニズムについて言えば、複数の単純なPythonパッケージから複雑なアプリケーションを作成することができます。 main:app: `Pyramid`アプリケーションで実行できるすべての設定文は、インクルードされたパッケージでも使用できます。ビュー、ルート、およびサブスクライバーを追加したり、認証および認可ポリシーを設定したりすることもできます。

必要に応じて、既存のアプリケーションの構成を独自に組み込んで変更することで、既存のアプリケーションの構成を拡張または上書きできます。

たとえば、すでに多数のルートがある既存のアプリケーションを再利用したい場合は、 `` include``ステートメントを `` route_prefix``を使って使うことができます。あなたがリクエストしたときに、そのアプリケーションのすべてのルートが利用可能になります:

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

if __name__ == '__main__':
   config = Configurator()
   config.include('pyramid_jinja2')
   config.include('pyramid_exclog')
   config.include('some.other.package', route_prefix='/somethingelse')

参考

ref: including_configuration`と:ref: building_an_extensible_app`も参照してください。

あなたの方法を認証する

:app: `Pyramid`は、あらかじめビルドされた、よくテストされた認証と承認の仕組みをそのままにして出荷します。スキームの使用は設定の問題です。したがって、後でアプローチを変更する必要がある場合は、設定を更新するだけで済みます。

さらに、認証と承認を処理するシステムは柔軟でプラグイン可能です。別のセキュリティアドオンを使用する場合や独自のセキュリティアドオンを定義する場合は、可能です。また、アプリケーション構成を変更して変更するだけで済みます。

参考

参照:ref: `enabling_authorization_policy`を参照してください。

リソースのツリーを構築する

:app: Pyramid`は、term: traversal`をサポートしています。これはURLを具象語:term: `resource tree`にマッピングする方法です。アプリケーションが異なるタイプのコンテンツ(CMSやDocument Management Systemなど)の任意の階層から構成されている場合、トラバーサルが適しています。非常にきめ細かなセキュリティモデル("Janeは* this フォルダ内のドキュメントを編集できますが、 * 1 "は編集できません)の要件がある場合、トラバーサルは強力なアプローチになります。

参考

ref: hello_traversal_chapter`と:ref: much_ado_about_traversal_chapter`も参照してください。

トゥイーンで各リクエストを処理する

:app: Pyramid`は:term: tween`と呼ばれる各要求または応答に任意のアクションを適用するシステムを持っています。システムは概念的にはWSGI:term: middleware`と似ていますが、term: tween`は:app: `Pyramid`コンテキストで実行され、テンプレート、リクエストオブジェクト、その他の細目。

:app: Pyramid`デバッグツールバーは:term: tween`であり、 `` pyramid_tm``トランザクションマネージャーと同じです。

参考

参照:ref: `registration_tweens`を参照してください。

あなたの意見からあなたが望むものを返す

:term: `renderer`は、ビューコードから単純なPython辞書を返すことを可能にします。しかし、いくつかのフレームワークでは、ビュー呼び出し可能オブジェクトから文字列またはタプルを返すことができます。フレームワークでこれが可能になると、インポートが少なくて済み、コードが少なくて済むので、コードはややきれいに見えます。たとえば、これを比較してください:

1
2
3
4
from pyramid.response import Response

def aview(request):
    return Response("Hello world!")

これに:

1
2
def aview(request):
    return "Hello world!"

見るのがよかったよね?

あなたが上記の2番目の例を実行しようとすると、app: `Pyramid`は例外を送出します。結局のところ、ビューは応答を返さなければならず、"明示的なものは暗黙のものより優れています"。

しかし、あなたが単純性の美しさを好む開発者であれば、:app: Pyramid`はこの種のものをサポートする手段を提供します:term: response adapter` :

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

def string_response_adapter(s):
    response = Response(s)
    response.content_type = 'text/html'
    return response

新しいレスポンスアダプタがコンフィグレーションに登録されます:

1
2
3
if __name__ == '__main__':
    config = Configurator()
    config.add_response_adapter(string_response_adapter, str)

これで、あなたのビューの呼び出し可能なものから文字列を返すことができます。

1
2
3
4
5
def helloview(request):
    return "Hello world!"

def goodbyeview(request):
    return "Goodbye world!"

:term: `レスポンスアダプタ 'を使って、カスタムコンテンツタイプと戻りコードを許可することもできます:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from pyramid.config import Configurator

def tuple_response_adapter(val):
    status_int, content_type, body = val
    response = Response(body)
    response.content_type = content_type
    response.status_int = status_int
    return response

def string_response_adapter(body):
    response = Response(body)
    response.content_type = 'text/html'
    response.status_int = 200
    return response

if __name__ == '__main__':
    config = Configurator()
    config.add_response_adapter(string_response_adapter, str)
    config.add_response_adapter(tuple_response_adapter, tuple)

これにより、これらのビューはどちらも期待どおりに動作します。

1
2
3
4
5
def aview(request):
    return "Hello world!"

def anotherview(request):
    return (403, 'text/plain', "Forbidden")

参考

参照:ref: `using_iresponse`も参照してください。

グローバルレスポンスオブジェクトを使用する

ビューは応答を返す必要があります。しかし、ビューコードでそれらを構築するのは雑用です。おそらく上記のように:term: `レスポンスアダプタ 'を登録することは多すぎる作業です。 :app: `Pyramid`はグローバルレスポンスオブジェクトも提供します。必要に応じて直接使用することができます:

1
2
3
4
5
def aview(request):
    response = request.response
    response.body = 'Hello world!'
    response.content_type = 'text/plain'
    return response

参考

ref: `request_response_attr`も参照してください。

拡張構成

おそらく、:app: `Pyramid`コンフィギュレータの構文が少し冗長であると感じます。あるいは、おそらく、開発者にコア・デベロッパーにapp: `Pyramid`自体を変更させることなく、フィーチャーを設定に追加したいのですか?

独自のディレクティブで:app: Pyramid 's:term:` configurator`を拡張することができます。たとえば、:meth: `pyramid.config.Configurator.add_view`を繰り返し呼び出しているとします。通常、既存のショートカットで退屈なものを取り除くことができますが、これはそうしたショートカットがない場合です:

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

config = Configurator()
config.add_route('xhr_route', '/xhr/{id}')
config.add_view('my.package.GET_view', route_name='xhr_route',
                xhr=True,  permission='view', request_method='GET')
config.add_view('my.package.POST_view', route_name='xhr_route',
                xhr=True, permission='view', request_method='POST')
config.add_view('my.package.HEAD_view', route_name='xhr_route',
                xhr=True, permission='view', request_method='HEAD')

かなり退屈な権利ですか?あなたは、:app: Pyramid:term:` configurator`にディレクティブを追加して、離れた場所のいくつかを自動化することができます:

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

def add_protected_xhr_views(config, module):
    module = config.maybe_dotted(module)
    for method in ('GET', 'POST', 'HEAD'):
        view = getattr(module, 'xhr_%s_view' % method, None)
        if view is not None:
            config.add_view(view, route_name='xhr_route', xhr=True,
                            permission='view', request_method=method)

config = Configurator()
config.add_directive('add_protected_xhr_views', add_protected_xhr_views)

それが終わったら、あなたは:term: `configurator`オブジェクトのメソッドとして今追加したディレクティブを呼び出すことができます:

1
2
config.add_route('xhr_route', '/xhr/{id}')
config.add_protected_xhr_views('my.package')

ずっといい!

設定コードを他の人と共有することもできます。コードをPythonパッケージに追加します。関数に:meth: `〜pyramid.config.Configurator.add_directive`を呼び出します。他のプログラマーがあなたのパッケージをインストールすると、自分の関数を:meth: `〜pyramid.config.Configurator.include`への呼び出しに渡すことで、あなたの設定を使うことができます。

参考

参照:ref: `add_directive`を参照してください。

アプリケーションのイントロスペクション

大規模でプラグイン可能なシステムを構築している場合は、アプリケーションランタイム*にプラグインされているもののリストを取得できることが便利です。たとえば、登録したビューのリストに基づいて、画面上部にタブのセットを表示することができます。

:app: Pyramid`は、この目的のために:term: introspector`を提供します。

以下は、ビュー内からapp: Pyramid 's:term:` introspector`を使用した例です:

1
2
3
4
5
6
7
8
9
from pyramid.view import view_config
from pyramid.response import Response

@view_config(route_name='bar')
def show_current_route_pattern(request):
    introspector = request.registry.introspector
    route_name = request.matched_route.name
    route_intr = introspector.get('routes', route_name)
    return Response(str(route_intr['pattern']))

参考

参照:ref: `using_introspection`を参照してください。