Pyramid Layout を使い始めるには、アプリケーションの config に pyramid_layout を含めてください:
config = Configurator(...)
config.include('pyramid_layout')
あるいは、 Configurator の include メソッドを使用する代わりに、次の行によりアプリケーションの .ini ファイルを変更することによって Pyramid Layout を有効にすることもできます:
pyramid.includes = pyramid_layout
アプリケーションに pyramid_layout をインクルードすることで、 add_layout と add_panel という2つの新しい ディレクティブが configurator に追加されます。これらの ディレクティブは、 add_view ととてもよく似た働きを しますが、 Layout と Panel のためのレジストリを追加します。 pyramid_layout をインクルードすることで、さらに各リクエストの リクエストオブジェクトに属性 (layout_manager) が追加されます。 それは LayoutManager の インスタンスです。
最後に、すべてのテンプレートで利用可能な 3 つのレンダラーグローバル変数が 追加されます: layout, main_template, panel です。 layout は現在のレイアウトの Layout クラス のインスタンスです。 main_template は、ビューに main template (別名 o-wrap) を 提供するテンプレートオブジェクトです。 panel (LayoutManager.render_panel のショートカット) は、 テンプレートの中で Panel をレンダリングするために使う callable です。
Layout は Layout クラス と main template から構成されます。 Layout クラスは、リクエスト毎に 引数としてコンテキストとリクエストを伴ってインスタンス化されます。 Layout クラスは省略可能で、その場合はデフォルトの Layout クラスが使用されます。 それは単に layout インスタンスに context と request を代入します。 しかし、テンプレートの中で利用可能な API を提供する場所として使える 自分自身の Layout クラスを提供するのが一般的でしょう。 単純な Layout クラスはこんな風になります:
class MyLayout(object):
page_title = 'Hooray! My App!'
def __init__(self, context, request):
self.context = context
self.request = request
self.home_url = request.application_url
def is_user_admin(self):
return has_permission(self.request, 'manage')
Layout インスタンス はレンダラーグローバル変数 layout としてテンプレートの中で利用可能です。例えば、テンプレートとして Mako または ZPT を使用していれば、テンプレートの中でこのように書くことが できます:
<title>${layout.page_title}</title>
Jinja2 では:
<title>{{layout.page_title}}</title>
すべての Layout には、その Layout の main template である 関連付けられたテンプレートがあり、それはレンダラーグローバル変数の中に main_template として存在します。
layout を登録するには、 configurator の add_layout メソッドを使用してください:
config.add_layout('myproject.layout.MyLayout',
'myproject.layout:templates/default_layout.pt')
上記の登録された Layout は、デフォルト Layout になるでしょう。 Layout は名前を付けることもできます:
config.add_layout('myproject.layout.MyLayout',
'myproject.layout:templates/admin_layout.pt',
name='admin')
これで Layout を作ったので、今度は特定のビューでそれを使用する番です。 Layout は、ビュー設定でレンダラーと並べて宣言的に定義できます:
@view_config(..., layout='admin')
def myview(context, request):
...
Pyramid < 1.4 では、名前付き Layout を使用するために、ビューの中で LayoutManager.use_layout メソッドを呼んでください:
def myview(context, request):
request.layout_manager.use_layout('admin')
...
traversal を使用していれば、ほとんどの場合 Layout に 名前を付ける必要がないことに気づくかもしれません。 Layout 設定に context 引数を使用することで、 context が特定の型で ある場合は常に特定の Layout を使うようにできます:
from ..models.wiki import WikiPage
config.add_layout('myproject.layout.MyLayout',
'myproject.layout:templates/wiki_layout.pt',
context=WikiPage)
同様に、 containment 引数は、特定の Layout を resource tree の全てのブランチで使用できるようにします:
from ..models.admin import AdminFolder
config.add_layout('myproject.layout.MyLayout',
'myproject.layout:templates/admin_layout.pt',
containment=AdminFolder)
デコレータ layout_config は、 Layout を宣言的に登録するために Configurator.scan と組み合わせて使えます:
from pyramid_layout.layout import layout_config
@layout_config(template='templates/default_layout.pt')
@layout_config(name='admin', template='templates/admin_layout.pt')
class MyLayout(object):
...
Layout を特定のコンテキスト型や containment に対して登録することも できます。詳しくは api docs を参照してください。
Panel はビューに似ていますが、ページの一部だけをレンダリング することに責任を持ちます。 Panel は任意の引数 (最初の2つは常に context と request です) を受け取る callable で、 ページに挿入するために html 文字列を返すか、または Pyramid レンダラーを 使用して html をレンダリングします。
ノート
プロジェクトの中でテンプレート言語を混在して使うことができます。 ある Panel は Jinja2 で実装し、ある Panel は Mako で、ある Panel は ZPT で、ということができます。 Pyramid Layout がサポートする任意のテンプレート言語で実装された Layout は、すべて動作します。
Panel は Configurator インスタンスの add_panel メソッド を使用して設定することができます:
config.add_panel('myproject.layout.siblings_panel', 'siblings',
renderer='myproject.layout:templates/siblings.pt')
Panel を引数付きで呼ぶことができるので、それらは 異なる方法で使用された時にパラメータ化することができます。 Panel callable は次のようなものです:
def siblings_panel(context, request, n_siblings=5):
return [sibling for sibling in context.__parent__.values()
if sibling is not context][:n_siblings]
そして、テンプレートからこのように呼ぶことができます:
${panel('siblings', 8)} <!-- Show 8 siblings -->
Configurator.scan を 使用する場合、 Panel を宣言的に登録することもできます:
from pyramid_layout.panel import panel_config
@panel_config('siblings', renderer='templates/siblings.pt')
def siblings_panel(context, request, n_siblings=5):
return [sibling for sibling in context.__parent__.values()
if sibling is not context][:n_siblings]
Panel は特定のコンテキスト型とだけマッチするように登録すること ができます。詳細については api docs を参照してください。
ビューテンプレートから main template に繋げるための正確な文法は、 使用しているテンプレート言語に依存して変わります。
あなたが ZPT ユーザなら、ビューテンプレートを Layout と その main template に接続することはかなり容易です。ビューテンプレート 中で最も外側の要素を単にこのようにしてください:
<metal:block use-macro="main_template">
...
</metal:block>
main template に明示的にマクロを定義する必要なしに テンプレートインスタンスをマクロとして使用 することが できるという Chameleon の特徴を利用していることに気づくでしょう。
その後は、あなたの予想した通りです。 main template は少なくとも 1つのスロットを定義しなければなりません。ビューテンプレートは少なくとも 1つのスロットを満たさなければなりません。
Mako で Layout から main template を使用するには、 ビューテンプレートの中の最初の行としてこれを使用してください:
<%inherit file="${context['main_template'].uri}"/>
main template では、ビューテンプレートが挿入してほしいポイント にこの行を挿入してください:
${next.body()}
Jinja2 については、 main template を Layout に対して 使用するために、ビューテンプレートの中の最初の行としてこれを使用してください:
{% extends main_template %}
それにより、通常の使い方と同様に main template で定義されたブロックを ビューテンプレートで定義されたブロックによってオーバーライドすることができます。