Upload
moriyoshi-koizumi
View
450
Download
0
Embed Size (px)
Citation preview
Rendererをカスタマイズする
@moriyoshit
For Pylonsはっかそん 2014.11
自己紹介
• Pylonsはっかそん初めてです
• 仕事でPyramidを2年ほど…
動機
• Requestによってレンダリングするテンプレートを変えたい
• Virtual hostみたいなものを想定
• それたぶんpyramid_layoutでできるよ?
• Exception viewはどうする?
• Requestに含まれる情報からレンダリングに必要な情報を作ってテンプレートに渡したい
• たとえば、CSSや画像へのパスなど
• これは BeforeRender event で inject してもいいけど、レンダリングの文脈でやりたい
add_view
permissionattrmapperhttp_cachePredicates
request_type / request_method / request_param / xhr / containment / wrapper / accept / header / context / decorator / match_param / check_csrf / effective_principals / physical_path
Pyramidのレンダリングのしくみ
View Deriver
RendererHelper
route_name
renderer
Create
Parameters
Create
(caller package)
Parameters
Pyramidのレンダリングのしくみ
Predicated view
Auth debug view
Secured view
Wrapped view
HTTP cached view
Rendered view
Mapped view
User-supplied view callable
View Deriver
Pyramidのレンダリングのしくみclass ViewDeriver(object):
def __init__(self, **kw):self.kw = kwself.registry = kw['registry']self.authn_policy =
self.registry.queryUtility(IAuthenticationPolicy)self.authz_policy =
self.registry.queryUtility(IAuthorizationPolicy)self.logger = self.registry.queryUtility(IDebugLogger)
def __call__(self, view):return self.attr_wrapped_view(
self.predicated_view(self.authdebug_view(
self.secured_view(self.owrapped_view(
self.http_cached_view(self.decorated_view(
self.rendered_view(self.mapped_view(
view)))))))))
Pyramidのレンダリングのしくみ
Rendered view
Mapped view
User-supplied view callable
RendererHelper
IRendererFactory
IRenderer
Dict-like
Lookup
IResponse
Create
Passing self as IRenderInfo
add_viewでの挙動
if isinstance(renderer, string_types):renderer = renderers.RendererHelper(
name=renderer, package=self.package,registry = self.registry)
渡されたrendererがstring typeであればRendererHelperでくるむそうでなければ、RendererHelperとしてそのままViewDeriverに渡す
カスタマイズポイント• IRenderFactoryを登録する (add_renderer)
• レンダラのルックアップ方法に縛られる• 拡張子• フルマッチ
• カスタムレンダラにconfiguration時にパラメータを渡す術がない
• RendererHelperを直接add_viewのrendererとして渡す
• RendererHelperのコンストラクタに渡すべきconfig.packageとconfig.registryは別途取得しておかないといけない
• @view_config decorator と相性が悪すぎる
結局どうしているか
• ILateBoundRendererHelperというインターフェイスを勝手に定義、コンストラクタでpackageとregistryを渡すのではなくて後からvenusianのscan時にbindできるようにした
• bind(package, registry)
• 上記のインターフェイスに対応したadd_viewとしてadd_lbr_viewというdirectiveを追加w
• add_lbr_viewに対応した@lbr_view_configを作った