お前誰よ
I aodag
I Atsushi ODAGiri
I 所属
I ビープラウド
I Pylonsproject.jp
3.
Pyramid
I 特徴
I Web アプリケーションフレームワーク
I ドキュメント、テストがしっかりしてるコミュニティ
I 長所
I 押しつけがない
I フレームワーク自体が拡張可能
I コンポーネントで整理された実装とAPI
I 短所
I 押し付けがない
I フルスタックでないので各種ライブラリの知識が必要
I 柔軟性の高さは諸刃の剣でもある
4.
使う理由
I SQLAlchemyと一緒に
I 認証方法や権限設定などがアプリケーションに絡んで複雑
I 保存先がDB でない場合などフルスタックがいらない
I アレがきらいだから
5.
pyramid の歴史
Irepoze.bfg 0.1 2008-07-08
I repoze.bfg 1.0 2009-07-05
I repoze.bfg 1.3b1 2010-10-25
I pyramid 1.0a1 2010-11-05
I pyramid 1.0 2011-01-30
I pyramid 1.1 2011-07-22
I pyramid 1.2 2011-09-12
I pyramid 1.3 2012-03-21
I pyramid 1.4 2012-12-18
I pyramid 1.5 2014-05-31
6.
インストール
$ pyvenv.py.venv
$ . .venv/bin/activate
(.venv)$ pip install pyramid
I pyvenv
I pip
7.
Hello Pyramid
frompyramid.config import Configurator
from pyramid_view import view_config
@view_config(route_name="hello")
def hello(request):
name = request.matchdict["name"]
body = "Hello {name}".format(name=name)
request.response.text = body
return request.response
def main(global_conf, **settings):
config = Configurator(settings=settings)
config.add_route("hello", "/hello/{name}")
config.scan(".")
return config.make_wsgi_app()
8.
Hello Pyramid
Iconfig.add_route
I Web アプリケーションで扱うURL パターンを登録する
I config.scan
I view_config などのvenusian デコレータのコールバックを実
行する
I view_config
I scan のタイミングでview を登録する
I request_method やroute_name などの条件を指定
9.
TODOLIST アプリケーションその1
Iモデル
I Task
I name
I 機能
I タスク一覧
I Task をすべて表示する
I タスク完了のボタンを表示する
I タスク追加のフォームを表示する
I タスク追加
I Task を作成して、タスク一覧に戻る
I タスク終了(削除)
I Task を削除して、タスク一覧に戻る
10.
SQLAlchemy を使う
pipinstall pyramid_tm pyramid_sqlalchemy
config.include("pyramid_tm")
config.include("pyramid_sqlalchemy")
I pyramid_tm
I transaction を利用した包括的なトランザクション管理
I エラー発生時はロールバック
I pyramid_sqlalchemy
I zope.sqlalchemy
I sqlalchemy.url
ビュー:タスク作成
@view_config(route_name="top",
request_method="POST")
def create_task(request):
name = request.params["name"]
task = Task(name=name)
DBSession.add(task)
location = request.route_url("top")
return HTTPFound(location)
I request.params
I request.route_url
I HTTPFound
14.
ビュー:タスク削除
@view_config(route_name="task_finish",
request_method="POST",
renderer="templates/index.mako")
def delete_task(request):
task_id = request.matchdict["task_id"]
task = Task.query.filter(Task.id == task_id).first()
if task is None:
raise HTTPNotFound
location = request.route_url("top")
return HTTPFound(location)
I request.matchdict
15.
Pyramid で使えるテンプレート
IPyramid1.0 から1.4 までmako, chameleon サポートが
Pyramid 自体に含まれていた
I Pyramid1.5 以降で標準サポートはstring, json のみ
I 標準サポート
I json
I string
I ライブラリでサポート
I pyramid_mako
I pyramid_chameleon
I pyramid_jinja2
I など
16.
pyramid_mako
pip installpyramid_mako
config.include("pyramid_mako")
I pyramid_mako
I mako テンプレートを使ったrenderer
I include すると“.mako” 拡張子で指定したレンダラーでmako
テンプレートを利用できる
TODOLIST アプリケーションその2
IRoute とTraversal とView を活用する
I アプリケーションのロジックはリソースで行うようにする
I CSS などを適用
I deform でフォームを作る
I Task をまとめるTodoList モデル
I ビューであれこれやらないようにする
21.
Pyramid のView が呼ばれるまで
I パターンマッチによりroute を決定
I route に設定されたfactory でresource を作成
I matchdict にtraverse がある場合はresource をトラバース
I 残りのURL を消費しきる
I リソースが__getitem__を持っていない
I 残りのURL が@@ で始まる(ビュー名)
I トラバース結果がcontext となる
I route, context, request method などの条件からview を決定
I view を呼び出す
22.
route とresource factory
config.add_route(
"task",
"/todolists/{todolist_id}/tasks/{task_id}/*traverse",
factory=".resources.task_factory")
I factory
ビューが呼び出されるまで
I URL:/todolist/1/tasks/2/@@finish
I Route: tasks にマッチ
I route_name: tasks
I todolist_id: 1
I task_id: 2
I travarse: @@finish
I tasks route のfactory であるtask_factory が呼び出される
I TaskResource インスタンスがリソースとして作成される
I URL の残りが@@finish となりトラバーサル終了
I ビュー名finish
I task_finish が呼び出される
27.
Deform/Colander でフォーム作成
IColander
I スキーマ、バリデーションライブラリ
I Deform
I フォームライブラリ
I Peppercorn
I HTML フォームで構造化したデータを扱うためのパーサー
28.
Deform/Colander/peppercorn の動作
Iappstruct, pstruct, cstruct
I アプリケーションモデルなどをappstruct にして渡す
I deform がappstruct をフォームウィジェットとともにHTML
にする
I ブラウザからsubmit されるとパラメータはpstruct で渡され
てくる
I peppercoron でpstruct をcstruct に変換
I colander でcstruct をappstruct に変換
29.
Colander スキーマ
importcolander as c
import deform.widget as w
class TodolistSchema(c.Schema):
name = c.SchemaNode(c.String())
description = c.SchemaNode(c.String(),
widget=w.RichTextWidget())
I Schema クラス
I SchemaNode
I widget
I deform へのヒントとしてウィジェットを設定する
I 抽象的なスキーマ情報にこういう詳細が入るのはちょっとや
だ(´・ω・`)
appstruct
class TodolistResource(object):
...
def appstruct(self):
return dict(name=self.todolist.name,
description=self.todolist.description)
I ビューのメソッドで詳細に実装したくない
I context に委譲
I FormView はなぜかcontext を持ってないのでrequest 経由で
取得
I appstruct
I deform はフォームの値をdict(appstruct) で受け取る
I appstruct はdeform によってpeppercorn が解釈可能なパラ
メータ(pstruct) をsubmit するフォームとなるようにレンダ
リングされる
33.
pyramid_deform のAPI はあまりきれいじゃない
I 継承ベース
I あまり大きく動作を変えられない
I メソッドオーバーライドによる穴埋め
I フォームバリデーション以外のデータを扱えない
I たとえばDB アクセスして重複チェックなどした場合のエ
ラーとかきれいに表示できない
I あまり多くを望まないように
I 単純なマスタデータ入力以上はできないと思ったほうがよい
34.
deform の扱い
form= deform.Form(TodolistSchema(), buttons=('save',))
controls = request.params.items()
try:
params = form.deserialize(controls)
except ValidationFailure as e:
return dict(form=e)
I request.params.items()
I peppercorn はパラメータの順番が重要
I ValidationFailure
I 入力チェックの例外オブジェクト
I エラー情報を含んだフォームをレンダリングする
35.
static_view
I CSS,JS などを取り扱うにはstatic_view を使う
add_static_view("static", "my.todolist:static")
I “static” はURL で使う名前
I “my.todolist:static” はファイルパスここではasset
specification 記法を使っている
I add_static_view で登録したasset はテンプレートなどで
static_url でURL を利用する
I static_url の例
<link rel="stylesheet"
href="${request.static_url(
'deform:static/css/bootstramp.min.css')}">
<script
src="${request.static_url(
'my.todolist:static/js/app.js')}"></script>
Mako テンプレート
Iblock タグ
I あとから継承先のテンプレートで埋める場所
I next.body()
I 直接継承しているテンプレートの内容をレンダリングする
I レイアウトなど多段に継承するときに必要
I inherit タグ
I 継承テンプレートを指定
I %for, %if, %while など
I Python の各種制御構文と同じ
I インデントブロックじゃないので、%endfor などが必要
pyramid のセキュリティ機構
Iauthentication_policy
I アクセスしているユーザーが誰なのか? を判定する方法
I authorization_policy
I アクセスするユーザーは何ができるのか? を判定する方法
43.
permission
@view_config(route_name="top",
permission="todolist.view",
renderer="templates/index.mako")
def index(context, request):
return dict(todolists=context)
I view ごとにpermission を決める
I authorization policy で与えられたpermission がview の
permission を含んでいれば、そのview を利用可能
I 適切なpermission を得られなかった場合はforbidden_view が
呼び出される
44.
ACLAuthorizationPolicy
class TodoListResource(object):
...
def __acl__(self):
return [(Allow, self.todolist.user.username,
'todolist.view'),
(Allow, self.todolist.user.username,
'todolist.edit'),
(Allow, self.todolist.user.username,
'task.create'),
]
I context の__acl__ プロパティでpermission を決定する
I __acl__は、pyramid1.5 以降はメソッドでもよい
I この場合はtodolist の持ち主ならtodolist.view などの
permission を与えられる
45.
ログインビュー
@view_config(route_name="login",
renderer="templates/login.mako")
class LoginView(FormView):
schema = LoginSchema()
buttons = ('login',)
def login_success(self, values):
user = authenticate(self.request,
values["username"],
values["password"])
if not user:
return
headers = security.remember(
self.request, user.username)
res = HTTPFound(self.request.route_url("top"),
headers=headers)
return res
46.
pyramid.security API
Isecurity.remember
I authentication_policy に対して、identity(ログインユーザーな
ど) を記録する(ログイン)
I security.forget
I authentication_policy に対して、identity を消去する(ログア
ウト)
47.
User の判定
defauthenticate(request, username, password):
user = User.query.filter(
User.username == username).first()
if not user:
return
if not user.validate_password(password):
return
return user
pyramid のjson 対応
I request.json_body
I リクエストから直接json パースしたオブジェクトを受け取
れる
I json レンダラー
I ビューが返すdict をjson にダンプしてくれる
I オブジェクトが__json__ メソッドを持っているとダンプ中
に呼び出される
I xhr プリディケーション
I view_config でxhr=True としておくと、jquery などのajax リ
クエストはそちらのビューが優先して呼び出される
結局リソースとは
I ビューとモデルの緩衝材
I アプリケーションモデル
I appstruct, __json__, __acl__ などフレームワークへのイン
ターフェイスを提供する
I アダプターパターン
I すべてをリソースでやろうとしないように
I なんでもありになりがち
I コンストラクタで受け取った以上のオブジェクトを扱わない
こと
53.
まとめ
I Pyramidはとても簡単
I 強力なライブラリを活用できる
I JSON アプリケーションのバックエンドとしても優秀
I SQLAlchemy は、がんばって勉強してください
54.
参考文献
I DefendingPyramid’s Design
I http://docs.pylonsproject.org/projects/pyra-mid/
en/1.5-branch/designdefense.html
I Pyramid Documentation
I http://docs.pylonsproject.org/en/latest/docs/pyramid.html
I Deform
I http://deform.readthedocs.org/en/latest/
I Colander
I http://colander.readthedocs.org/en/latest
I pyramid_sqlalchemy
I http://pyramid-sqlalchemy.readthedocs.org/en/latest/
I pyramid_tm
I http://pyramid-tm.readthedocs.org/en/latest/