(機械翻訳) リソース¶
A:term: resource`は、アプリケーションに関連するツリー内の"場所"を表すオブジェクトです。 Every:app: `Pyramid`アプリケーションは、少なくとも一つのリソースオブジェクトを持っています::term: root`リソース。 rootリソースを手動で定義しなくても、デフォルトのものが作成されます。 rootリソースは:term: `resource tree`のルートです。リソースツリーは、ネストされた辞書的なオブジェクトのセットで、これを使用してWebサイトの構造を表現できます。
:term: traversal`を使用してURLをコードにマッピングするアプリケーションでは、リソースツリー構造は各URLを:term: view callable`にマップするために非常に使用されます。 :term: traversal`が使われるとき、:app: Pyramid`は:term: `context`リソースを見つけるために、ネストされた辞書構造をたどってリソースツリーを歩きます。コンテキストリソースが見つかると、要求の中のコンテキストリソースとデータを使用して:term: `view callable`が検索されます。
term: `URL dispatch`を使用するアプリケーションでは、リソースツリーは間接的にのみ使用され、しばしば開発者にとっては「見えない」ものです。 URLディスパッチアプリケーションでは、リソース "ツリー"はしばしばルートリソースだけで構成されます。このルートリソースには、セキュリティ宣言が添付されていることがありますが、必須ではありません。一般に、リソースツリーは、トラバーサルを使用するアプリケーションよりもURLディスパッチを使用するアプリケーションで重要性が低くなります。
"Zope-like ":app: `Pyramid`アプリケーションでは、リソースオブジェクトはしばしば永続的にデータを格納し、永続データの変更に関連するメソッドを提供します。この種のアプリケーションでは、リソースはWebサイトのサイト構造を表すだけでなく、アプリケーションの用語: `ドメインモデル 'になります。
また、
- :meth: 〜pyramid.config.Configurator.add_view`(またはa:func:〜pyramid.view.view_config`デコレータ)は、リソースクラスまたはリソースを参照します。 :term: インタフェース。
- A:term: `root factory`はリソースを返します。
- リソースは、ビューのterm: context:term:` view`コードに公開されます。
- さまざまな有用な:app: Pyramid APIメソッドはリソースを引数として期待します(例::meth:`〜pyramid.request.Request.resource_url`など)。
リソースツリーの定義¶
:term: traversal`が(純粋に:term: URLディスパッチ ベースのアプリケーションとは対照的に)使用されるとき、:app: Pyramid`は、リソースで構成される木をトラバースできることを期待していますツリー)。トラバーサルはルート・リソースから始まり、再帰的にツリーに下がり、各リソースの `` __getitem__``メソッドを試して、パス・セグメントを別のリソース・オブジェクトに解決します。 :app: `Pyramid`はツリー内のリソースインスタンスに以下のポリシーを課します:
- コンテナリソース(他のリソースを含むリソース)は、ユニコード名をサブリソースに解決しようとする `` __getitem__``メソッドを提供しなければなりません。特定の名前のサブリソースがコンテナリソースに存在しない場合、コンテナリソースの `` __getitem__``メソッドは:exc: KeyError`を送出する必要があります。その名前のサブリソース*が存在する場合、コンテナの ` __getitem__``はサブリソースを返すべきです。
- 他のリソースを持たないリーフリソースは、 `` __getitem__``を実装してはいけません。あるいは、 `` __getitem__``メソッドは常に:exc: `KeyError`を生成しなければなりません。
トラバーサルがリソースインスタンスに対してどのように動作するかについては、:ref: `traversal_chapter`を参照してください。
次に、 `` root``という名前の変数で表されるリソースツリーの例を示します。
1 2 3 4 | class Resource(dict):
pass
root = Resource({'a':Resource({'b':Resource({'c':Resource()})})})
|
上記で作成したリソースツリーは、 `` 'a``という名前の単一の子を持つ辞書的なルートオブジェクトによって表されます。 `` a'``には `` b'``という名前の単一の子があり、 `` b'``には子を持たない `` c'``という名前の単一の子があります。したがって、 `` 'c' `葉資源にアクセスすることは可能です:
1 | root['a']['b']['c']
|
上記の `` root``オブジェクトを:term: ルートファクトリ`から返すと、パス ` / a / b / c``はリソースツリーの `` c'``オブジェクトをの結果:term: traversal
この例では、ツリー内の各リソースは同じクラスです。これは要件ではありません。ツリー内のリソース要素は任意のタイプでよい。簡単にするために、ツリー内のすべてのリソースを表すために単一のクラスを使用しましたが、実際のアプリケーションでは、ツリー内のリソースは任意です。
上の例のツリーはトラバーサルを処理できますが、上の例のリソースインスタンスは:term: location`を認識していないので、"実"アプリケーションでのそれらのユーティリティは制限されています。組み込み:app: `Pyramid API機能を最大限に活用するには、リソースを「位置認識」する必要があります。次のセクションでは、リソースに位置を認識させる方法を詳しく説明します。
位置認識リソース¶
特定の:app: Pyramid`の場所、セキュリティ、URL生成、およびトラバーサルAPIがリソースツリー内のリソースに対して適切に動作するためには、ツリー内のすべてのリソースがterm: location`を意識していなければなりません。つまり、 `` __parent__``と `` __name__``という2つの属性を持たなければなりません。
ロケーション認識リソースの `` __parent__``属性は、ツリー内のリソースの親リソースインスタンスへの参照である必要があります。 `` __name__``属性は、リソースの親が `` __getitem__``を介してリソースを参照する名前でなければなりません。
ルートリソースの `` __parent__``は `` None``で、 `` __name__``は空の文字列でなければなりません。例えば:
1 2 3 | class MyRootResource(object):
__name__ = ''
__parent__ = None
|
ルートリソースの `` __getitem__``メソッドから返されるリソースは、ルートリソースへの参照である `` __parent__``属性を持ち、 `` __name__``属性は、そのリソースを経由して到達可能な名前と一致する必要がありますrootリソースの `` __getitem__``です。ルートリソース内のコンテナリソースには、コンテナを指す `` __parent__``属性を持つリソースを返す `` __getitem__``が必要です。これらのサブオブジェクトには、名前に一致する `` __name__``属性が必要ですそれによって、コンテナから `` __getitem__``を介して取得されます。このパターンはルートからツリーを再帰的に"上に"続けます。
各リソースの `` __parent__``属性はルートに向かって"下向き"を指すリンクリストを形成します。これはファイルシステムディレクトリの `` ..``エントリに似ています。リソースツリー内の任意のリソースから `` __parent__``の値に従えば、 `` cd ..``ファイルシステムコマンドを実行し続けるのと同じように、最終的にはルートリソースに来るでしょう。ルートディレクトリ。
警告
あなたのルートリソースが `` None``や空文字列でない `` __name__``引数を持っている場合、:func: 〜pyramid.request.Request.resource_url`関数によって返されたURLと: func: `〜pyramid.traversal.resource_path`と:func:〜pyramid.traversal.resource_path_tuple` APIが正しく生成されません。 `` __name__``の値は、すべてのパスと生成されたURLの前に付加されます(単一の先頭のスラッシュまたは空のタプル要素とは対照的に)。
tree-walking:app: Pyramid APIを使用するアプリケーションは、位置認識のリソースを必要とします。これらのAPIには、meth: 〜pyramid.request.Request.resource_url、:func:〜pyramid.traversal.find_resource、:func: 〜pyramid.traversal.find_root、:func(これらに限定されません) :func: 〜pyramid.traversal.find_interface、:func:〜pyramid.traversal.resource_path、:func: 〜pyramid.traversal.resource_path_tuple、:func:〜pyramid.traversal.traverse、:func: ` 〜pyramid.traversal.virtual_root`、および(通常):meth: 〜pyramid.request.Request.has_permission`と:func:〜pyramid.security.principals_allowed_by_permission`のようになります。
一般的に、app: `Pyramid`インフラストラクチャは位置認識リソースに依存するので、ツリー内の各リソースを位置認識できるようにすることをお勧めします。
リソースのURLの生成¶
あなたのリソースが:term: location`を意識しているなら、:meth: pyramid.request.Request.resource_url` APIを使ってリソースのURLを生成することができます。このURLは、親ツリー内のリソースの位置を使用してリソースパスを作成し、現在のアプリケーションURLをパスの先頭に付けて、スキーム、ホスト、ポート、およびパスで完全修飾URLを形成します。 :meth: `〜pyramid.request.Request.resource_url`に追加の引数を渡して、生成されたURLに影響を与えることもできます。
最も単純な:meth: `〜pyramid.request.Request.resource_url`の呼び出しは次のようになります:
1 | url = request.resource_url(resource)
|
上の例の `` request``は、:app: Pyramid:term:` request`オブジェクトのインスタンスです。
上の例で `` resource``と呼ばれるリソースがルートリソースで、サーバとの接続に使用されたホストが `` example.com``だった場合、生成されるURLは `` http:// example.com / ``しかし、リソースが `` a``という名前のルートリソースの子であった場合、生成されるURLは `` http:// example.com / a / ``になります。
リソースが階層の"場所"であり、URLが意図されているので、:meth: `〜pyramid.request.Request.resource_url`がこの単純な方法でそれらを生成するために使用されるとき、すべてのリソースURLにスラッシュが追加されますクリックして訪問する。リソースのデフォルトビューの結果としてレンダリングされるHTMLページに含める相対URLは、親に対する相対URLよりも相対的に相対的にリソースに関連しています。
余分な要素を渡すこともできます:meth: 〜pyramid.request.Request.resource_url:
1 | url = request.resource_url(resource, 'foo', 'bar')
|
上の例で `` resource``と呼ばれるリソースがルートリソースで、サーバとの接続に使用されたホストが `` example.com``だった場合、生成されるURLは `` http:// example.com / foo / bar``を実行します。特別な位置引数として、任意の数の余分な要素を:meth: `〜pyramid.request.Request.resource_url`に渡すことができます。余分な要素が渡されると、リソースのURLに追加されます。要素が渡されると、最後のセグメントにスラッシュが追加されません。
クエリ文字列を渡すこともできます:
1 | url = request.resource_url(resource, query={'a':'1'})
|
上の例で `` resource``と呼ばれるリソースがルートリソースで、サーバとの接続に使用されたホストが `` example.com``だった場合、生成されるURLは `` http:// example.com/?a = 1``。
a:term: virtual root`がアクティブな場合、リソースの:meth:〜pyramid.request.Request.resource_url`で生成されたURLは、その物理的なツリーパスよりも "短く"なります。仮想的にリソースを根絶することについての詳細は、:ref: `virtual_root_support`を参照してください。
リソースURLの生成の詳細については、:meth: `pyramid.request.Request.resource_url`のドキュメントを参照してください。
リソースURL生成のオーバーライド¶
リソースオブジェクトが `` __resource_url__``メソッドを実装している場合、このメソッドは:meth: 〜pyramid.request.Request.resource_url`が呼び出され、リソースのURLを生成し、リソースに対して返されるデフォルトのURLをオーバーライドしますby:meth: `〜pyramid.request.Request.resource_url。
`` __resource_url__``フックには、 `` request``と `` info``という2つの引数が渡されます。 `` request``は:meth: 〜pyramid.request.Request.resource_url`に渡される:term: request`オブジェクトです。 `` info``は以下のキーを持つ辞書です:
- `` physical_path``
- `` pyramid.traversal.resource_path(resource) ``で定義されている、リソースに対して計算された"物理パス"を表す文字列。それはスラッシュで始まり、スラッシュで終わります。
- `` virtual_path``
- :ref: `virtual_root_support`で定義されているように、リソースに対して計算された"仮想パス"を表す文字列。仮想ルートが有効になっていない場合、これは物理パスと同じです。それはスラッシュで始まり、スラッシュで終わります。
- `` app_url``
- `` request.resource_url``の間に生成されたアプリケーションURLを表す文字列です。スラッシュで終わることはありません。これは潜在的にカスタマイズされたURLプレフィックスを表し、ユーザーが `` request.resource_url``に渡す可能性のあるカスタムスキーム、ホスト、ポート情報を含みます。 `` request.application_url``の使用よりも優先すべきです。
リソースの `` __resource_url__``メソッドは、URLを表す文字列を返さなければなりません。デフォルトを上書きできない場合は `` None``を返します。 `` None``を返すと、デフォルトのURLが返されます。
次に、 `` __resource_url__``メソッドの例を示します。
1 2 3 | class Resource(object):
def __resource_url__(self, request, info):
return info['app_url'] + info['virtual_path']
|
上の例は実際には、デフォルトの `` resource_url``機構によって生成されたデフォルトURLを生成して返しますが、コードは必要に応じて任意のロジックを実行できます。たとえば、コードで生成されたURLのホスト名またはポート番号を上書きすることができます。
`` __resource_url__``で生成されたURLは完全修飾でなければならず、スラッシュで終わっていて、クエリー文字列やアンカー要素(パス要素のみ)を含めてはいけません:meth: 〜pyramid.request.Request .resource_url。
リソースへのパスの生成¶
:func: `pyramid.traversal.resource_path`は、リソースツリー内の位置に基づいて、リソースオブジェクトの絶対的な物理パスを表す文字列オブジェクトを返します。パスの各セグメントはスラッシュ文字で区切られています。
1 2 | from pyramid.traversal import resource_path
url = resource_path(resource)
|
上記の例の `` resource``が `` root ['a'] ['b'] ``としてツリーにアクセス可能であった場合、上の例は文字列 `` / a / b``を生成します。
:func: `〜pyramid.traversal.resource_path`に渡された位置引数は、パスのセグメントとしてリソースパスの末尾に追加されます。
1 2 | from pyramid.traversal import resource_path
url = resource_path(resource, 'foo', 'bar')
|
上記の例の `` resource``が `` root ['a'] ['b'] ``としてツリー内でアクセス可能であった場合、上記の例では文字列 `` / a / b / foo / bar` `。
渡されるリソースは、term: location-awareでなければなりません。
a:term: virtual root`の有無は:func:〜pyramid.traversal.resource_path`の動作に影響しません。
パスによるリソースの検索¶
リソースへの文字列パスがある場合は、func: `pyramid.traversal.find_resource`を使用して、アプリケーションのリソースツリーのその場所からリソースを取得できます。
絶対パスを解決するには、 `` / ``で始まる文字列を `` path``引数として渡します:
1 2 | from pyramid.traversal import find_resource
url = find_resource(anyresource, '/path')
|
あるいは、 `` / ``を前置しない文字列を渡して:func: `pyramid.traversal.find_resource`に渡すリソースに関連するパスを解決することができます:
1 2 | from pyramid.traversal import find_resource
url = find_resource(anyresource, 'path')
|
func: 〜pyramid.traversal.find_resource`は、:func:〜pyramid.traversal.resource_path` APIによって生成されることがよくあります。これらのAPIはお互いの「ミラー」です。
:func: 〜pyramid.traversal.find_resource`(ツリー内のそれぞれのリソースが存在しない場合)を呼び出すときにパスを解決できない場合、a:exc: KeyError`が送出されます。
リソースへのパスを解決する方法の詳細については、:func: `pyramid.traversal.find_resource`のドキュメントを参照してください。
リソースの系統を取得する¶
:func: pyramid.location.lineage:term:` location`-aware:term: resource`オブジェクトの:term: lineage`を表すジェネレータを返します。
:func: `〜pyramid.location.lineage`関数は、それに渡されたリソースを返し、次にリソースの各親を順番に返します。たとえば、リソースツリーが次のように構成されているとします。
1 2 3 4 5 | class Thing(object): pass
thing1 = Thing()
thing2 = Thing()
thing2.__parent__ = thing1
|
`` lineage(thing2) `'を呼び出すとジェネレータが返されます。リストにすると、次のようになります:
1 2 | list(lineage(thing2))
[ <Thing object at thing2>, <Thing object at thing1> ]
|
:func: 〜pyramid.location.lineage`によって返されたジェネレータは、最初に渡されたリソースを無条件で返します。次に、リソースが ` __parent__``属性を与えた場合、 `` resource .__ parent__``で表されるリソースを返します。 *そのリソースが `` __parent__``属性を持つ場合、検査対象リソースに `` __parent__``属性がないか、 `` __parent__``属性が `` __parent__``属性になるまで、そのリソースの親を返します。 「なし」。
詳細については、func: `pyramid.location.lineage`のドキュメントを参照してください。
リソースが別のリソースのリネージにあるかどうかの判断¶
:func: pyramid.location.inside`関数を使用して、あるリソースが別のリソースの:term: lineage`にあるかどうかを判断します。
たとえば、リソースツリーが以下の場合:
1 2 3 4 5 | class Thing(object): pass
a = Thing()
b = Thing()
b.__parent__ = a
|
`` inside(b、a) を呼び出すと True``が返されます。 b``には a``を含む系統があるからです。しかし、 ` inside(a、b) 'を呼び出すと、 a``に b``を含む系統がないので `False``を返します。
:func: 〜pyramid.location.inside`の引数リストは (resource1、resource2) です。 ` resource2``が `` resource1``の :term: lineage`の祖先である場合、 `` resource1``は"inside " `` resource2``です。親(または親の親など)が祖先である場合、それは系統の祖先です。
詳細は、func: `pyramid.location.inside`を参照してください。
ルートリソースの検索¶
:func: pyramid.traversal.find_root APIを使って:term:` root`リソースを見つけてください。ルートリソースは:term: リソースツリー 'のルートにあるリソースです。 APIは単一の引数 ` resource``を受け入れます。これは、term: `location`を意識したリソースです。これは、ツリー内でルートを検索する任意のリソースにすることができます。
たとえば、リソースツリーが以下の場合:
1 2 3 4 5 | class Thing(object): pass
a = Thing()
b = Thing()
b.__parent__ = a
|
`` find_root(b) ``を呼び出すと `` a``が返されます。
ルートリソースは:term: view callable`コード内で `request.root``として利用することもできます。
a:term: virtual root`の有無は:func:〜pyramid.traversal.find_root`の動作に影響を与えません。返されるルートオブジェクトは常に* physical *ルートオブジェクトです。
インタフェースを実装するリソース¶
リソースは:term: interface`を実装するためにオプションで作ることができます。インタフェースは、後で:term: `view configuration`と:func: pyramid.traversal.find_interface`で参照できる"type "でリソースオブジェクトをタグ付けするために使用されます。
:term: view configuration`文内の context``または `containment``述語引数としてクラスの代わりにインタフェースを指定すると、複数のクラスのリソースオブジェクトに対して呼び出し可能な単一のビューを使用することができます。アプリケーションが単純なので、これをやりたい理由がない場合は、この章のこのセクションを読み飛ばしてください。
たとえば、ブログエントリが:term: `interface`を実装していることを宣言するブログエントリを記述するコードがあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import datetime
from zope.interface import implementer
from zope.interface import Interface
class IBlogEntry(Interface):
pass
@implementer(IBlogEntry)
class BlogEntry(object):
def __init__(self, title, body, author):
self.title = title
self.body = body
self.author = author
self.created = datetime.datetime.now()
|
このリソースは、リソースコンストラクタを `` BlogEntry``クラスとして定義するクラスと、 `` IBlogEntry`を使用する `` implementer``クラスデコレータを介してクラスに付加される:term: `interface`の2つの要素から成ります。 `インターフェイスを唯一の引数として使用します。
使用されるインタフェースオブジェクトは、class: `zope.interface.Interface`から継承するクラスのインスタンスでなければなりません。
リソースクラスは、0以上のインタフェースを実装することができる。 :func: zope.interface.implementer`関数をクラスデコレータとして使用して、リソースがインタフェースを実装するように指定します。上記の ` BlogEntry``リソースは `` IBlogEntry``インターフェースを実装しています。
特定のリソース*インスタンス*がそのクラスではなくインタフェースを提供するように指定することもできます。クラスがインタフェースを実装すると宣言すると、そのクラスのすべてのインスタンスもそのインタフェースを提供します。しかし、単一のオブジェクトがインタフェースを提供すると言うこともできます。これを行うには、:func: `zope.interface.directlyProvides`関数を使います:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import datetime
from zope.interface import directlyProvides
from zope.interface import Interface
class IBlogEntry(Interface):
pass
class BlogEntry(object):
def __init__(self, title, body, author):
self.title = title
self.body = body
self.author = author
self.created = datetime.datetime.now()
entry = BlogEntry('title', 'body', 'author')
directlyProvides(entry, IBlogEntry)
|
:func: `zope.interface.directlyProvides`は、以前にインスタンスによって提供された既存のインタフェースを置き換えます。リソースオブジェクトに、すでに置き換えたくないインスタンスレベルのインタフェース宣言がある場合は、:func: `zope.interface.alsoProvides`関数を使用してください:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import datetime
from zope.interface import alsoProvides
from zope.interface import directlyProvides
from zope.interface import Interface
class IBlogEntry1(Interface):
pass
class IBlogEntry2(Interface):
pass
class BlogEntry(object):
def __init__(self, title, body, author):
self.title = title
self.body = body
self.author = author
self.created = datetime.datetime.now()
entry = BlogEntry('title', 'body', 'author')
directlyProvides(entry, IBlogEntry1)
alsoProvides(entry, IBlogEntry2)
|
:func: zope.interface.alsoProvides`は、インスタンスによって直接提供されるインタフェースのセットを、func: zope.interface.directlyProvides`のように上書きするのではなく、追加します。
ビューの設定でリソースインタフェースを使用する方法の詳細については、:ref: `using_resource_interfaces`を参照してください。
リネージのクラスまたはインターフェイスを持つリソースの検索¶
:func: 〜pyramid.traversal.find_interface APIを使って特定のPythonクラスの親を見つけるか、あるいは:term:` interface`を実装します。
たとえば、リソースツリーが次のように構成されているとします。
1 2 3 4 5 6 | class Thing1(object): pass
class Thing2(object): pass
a = Thing1()
b = Thing2()
b.__parent__ = a
|
`` a``がクラス `` Thing1``であるため、 `` find_interface(a、Thing1) ``を呼び出すと `` a``リソースが返されます(最初の引数として渡されるリソースは最初に考慮され、クラスまたはインターフェイスの仕様が一致します)。
「find_interface(b、Thing1)」を呼び出すと、 `` a``がクラス `` Thing1``で `` a``が `` b``の最初のリソースであるため、 `` a``リソースを返しますこのクラスの系譜。
`` find_interface(b、Thing2) ``を呼び出すと、 `` b``リソースが返されます。
`` find_interface``の2番目の引数は、クラスではなくterm: `interface`でもかまいません。それがインタフェースである場合、系統内の各リソースは、そのリソースがクラスであるかどうかを見るのではなく、特定のインタフェースを実装しているかどうかを調べるためにチェックされます。
参考
参照:ref: `resources_which_implement_interfaces`も参照してください。
:app:Pyramid API関数¶
リソースオブジェクトは、ビューに提供される:term: context`として使用されます。リソースオブジェクトがどのようにコンテキストになるかについては、:ref: `traversal_chapter`と:ref: urldispatch_chapter`を参照してください。
:ref: `traversal_module`によって提供されるAPIは、リソースオブジェクトに対して使用されます。これらの関数は、リソースの "パス"、リソースツリーのルートリソース、またはリソースのURLを生成するために使用できます。
:ref: `location_module`によって提供されるAPIは、リソースに対して使用されます。これらは、リソースツリーを歩き回るか、別のリソースを別の場所に配置するのに便利です。
:class: pyramid.request.Request`上のいくつかのAPIは、リソースオブジェクトをパラメータとして受け入れます。たとえば、:meth: `〜pyramid.request.Request.has_permission APIは、引数の1つとしてリソースオブジェクトを受け入れます。 ACLはこのリソースまたはその祖先の1つから取得されます。 :class: pyramid.request.Request`クラスの他のセキュリティ関連APIは引数としてterm: context`を受け入れ、コンテキストは常にリソースです。