SlideShare ist ein Scribd-Unternehmen logo
1 von 54
Downloaden Sie, um offline zu lesen
Pyramid 入門 
aodag 
September 15, 2014
お前誰よ 
I aodag 
I Atsushi ODAGiri 
I 所属 
I ビープラウド 
I Pylonsproject.jp
Pyramid 
I 特徴 
I Web アプリケーションフレームワーク 
I ドキュメント、テストがしっかりしてるコミュニティ 
I 長所 
I 押しつけがない 
I フレームワーク自体が拡張可能 
I コンポーネントで整理された実装とAPI 
I 短所 
I 押し付けがない 
I フルスタックでないので各種ライブラリの知識が必要 
I 柔軟性の高さは諸刃の剣でもある
使う理由 
I SQLAlchemy と一緒に 
I 認証方法や権限設定などがアプリケーションに絡んで複雑 
I 保存先がDB でない場合などフルスタックがいらない 
I アレがきらいだから
pyramid の歴史 
I repoze.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
インストール 
$ pyvenv.py .venv 
$ . .venv/bin/activate 
(.venv)$ pip install pyramid 
I pyvenv 
I pip
Hello Pyramid 
from pyramid.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()
Hello Pyramid 
I config.add_route 
I Web アプリケーションで扱うURL パターンを登録する 
I config.scan 
I view_config などのvenusian デコレータのコールバックを実 
行する 
I view_config 
I scan のタイミングでview を登録する 
I request_method やroute_name などの条件を指定
TODOLIST アプリケーションその1 
I モデル 
I Task 
I name 
I 機能 
I タスク一覧 
I Task をすべて表示する 
I タスク完了のボタンを表示する 
I タスク追加のフォームを表示する 
I タスク追加 
I Task を作成して、タスク一覧に戻る 
I タスク終了(削除) 
I Task を削除して、タスク一覧に戻る
SQLAlchemy を使う 
pip install 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
Route の登録 
I add_route 
# タスク一覧、タスク作成 
config.add_route("top", "/") 
# タスク削除 
config.add_route( 
"task_finish", 
"/tasks/{task_id}/finish")
ビュー:タスク一覧 
@view_config(route_name="top", 
request_method="GET", 
renderer="templates/index.mako") 
def index(request): 
tasks = Task.query.all() 
return dict(tasks=tasks) 
I route_name 
I request_method 
I renderer
ビュー:タスク作成 
@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
ビュー:タスク削除 
@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
Pyramid で使えるテンプレート 
I Pyramid1.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 など
pyramid_mako 
pip install pyramid_mako 
config.include("pyramid_mako") 
I pyramid_mako 
I mako テンプレートを使ったrenderer 
I include すると“.mako” 拡張子で指定したレンダラーでmako 
テンプレートを利用できる
テンプレート:タスク一覧 
<ul> 
%for task in tasks: 
<li> 
${task.name} 
<form action="${request.route_url('task_finish', 
task_id=task.id)}" 
method="post"> 
<button type="submit">Finish</button> 
</form> 
</li> 
%endfor 
</ul>
テンプレート:タスク作成フォーム 
<form action="${request.route_url('top')}" method="post"> 
<input type="text" name="name"> 
<button type="submit">Add</button> 
</form>
TODOLIST アプリケーションその2
TODOLIST アプリケーションその2 
I Route とTraversal とView を活用する 
I アプリケーションのロジックはリソースで行うようにする 
I CSS などを適用 
I deform でフォームを作る 
I Task をまとめるTodoList モデル 
I ビューであれこれやらないようにする
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 を呼び出す
route とresource factory 
config.add_route( 
"task", 
"/todolists/{todolist_id}/tasks/{task_id}/*traverse", 
factory=".resources.task_factory") 
I factory
resource factory 
def task_factory(request): 
todolist_id = request.matchdict["todolist_id"] 
task_id = request.matchdict["task_id"] 
task = Task.query.filter( 
Task.id == task_id, 
Task.todolist_id == todolist_id).first() 
if taks is None: 
raise HTTPNotFound 
return TaskResource(task, request)
アダプター 
class TaskResource(object): 
def __init__(self, task, request): 
self.task = task 
self.request = request 
def finish(self): 
self.task.finish() 
@property 
def todolist_url(self): 
return self.request.route_url( 
"todolist", 
todolist_id=self.task.todolist_id) 
I task ラップする対象 
I request API 呼び出しのために必要
view 
@view_config( 
route_name="task", 
name="finish", 
context=".reources.TaskResource", 
request_method="POST") 
def task_finish(context, request): 
context.finish() 
return HTTPFound(location=context.todolist_url) 
I view はコンテキストにイベントを伝える(メソッドを呼び出 
す)だけ
ビューが呼び出されるまで 
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 が呼び出される
Deform/Colander でフォーム作成 
I Colander 
I スキーマ、バリデーションライブラリ 
I Deform 
I フォームライブラリ 
I Peppercorn 
I HTML フォームで構造化したデータを扱うためのパーサー
Deform/Colander/peppercorn の動作 
I appstruct, pstruct, cstruct 
I アプリケーションモデルなどをappstruct にして渡す 
I deform がappstruct をフォームウィジェットとともにHTML 
にする 
I ブラウザからsubmit されるとパラメータはpstruct で渡され 
てくる 
I peppercoron でpstruct をcstruct に変換 
I colander でcstruct をappstruct に変換
Colander スキーマ 
import colander 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 抽象的なスキーマ情報にこういう詳細が入るのはちょっとや 
だ(´・ω・`)
pyramid_deform 
@view_config(....) 
class TodolistForm(FormView): 
schema = TodolistSchema() 
buttons = ('save',) 
@property 
def context(self): 
return self.request.context 
def save_success(self, values): 
todolist = self.context.add_todolist(**values) 
return HTTPFound(todolist.url) 
I FormView を継承してビューを実装する 
I schema でcolander スキーマを指定 
I buttons でボタンの名前(‘save’) を設定しておくと、対応する 
メソッド(save_success) がバリデーション後に呼び出される
フォームのデフォルト値 
class EditTodolistForm(FormView): 
schema = TodolistSchema() 
buttons = ('save',) 
@property 
def context(self): 
return self.request.context 
def apptsruct(self): 
return self.context.appstruct() 
def save_success(self, values): 
todolist = self.context 
todolist.update(**values) 
return HTTPFound(todolist.url)
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 するフォームとなるようにレンダ 
リングされる
pyramid_deform のAPI はあまりきれいじゃない 
I 継承ベース 
I あまり大きく動作を変えられない 
I メソッドオーバーライドによる穴埋め 
I フォームバリデーション以外のデータを扱えない 
I たとえばDB アクセスして重複チェックなどした場合のエ 
ラーとかきれいに表示できない 
I あまり多くを望まないように 
I 単純なマスタデータ入力以上はできないと思ったほうがよい
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 エラー情報を含んだフォームをレンダリングする
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>
Asset Specification 
I “{package}:{directory}” のような文字列でパッケージ以下 
のディレクトリを表す 
I my.todolist:static は 
os.path.join(os.path.dirname(my.todolist.__file__), “static”) 
で取得できるディレクトリ
ベーステンプレート 
<html> 
<head> 
<link rel="stylesheet" 
href="${request.static_url( 
'deform:static/css/bootstramp.min.css')}"> 
<%block name="extra_header"></%block> 
</head> 
<body> 
<div class="container"> 
${next.body()} 
</div> 
</body> 
</html>
テンプレート 
<%inherit file="base.mako"> 
<%block name="extra_header> 
%for reqt in css_links: 
<link rel="stylesheet" 
href="${request.static_url(reqt)}" 
type="text/css" /> 
%endfor 
... 
</%block>
Mako テンプレート 
I block タグ 
I あとから継承先のテンプレートで埋める場所 
I next.body() 
I 直接継承しているテンプレートの内容をレンダリングする 
I レイアウトなど多段に継承するときに必要 
I inherit タグ 
I 継承テンプレートを指定 
I %for, %if, %while など 
I Python の各種制御構文と同じ 
I インデントブロックじゃないので、%endfor などが必要
TODOLIST アプリケーションその3 
I User モデルを追加 
I 認証、権限を追加
security 
def includeme(config): 
secret = config.registry.settings['session.secret'] 
session_factory = SignedCookieSessionFactory( 
secret=secret) 
config.set_session_factory(session_factory) 
authentication_policy = SessionAuthenticationPolicy() 
authorization_policy = ACLAuthorizationPolicy() 
config.set_authentication_policy( 
authentication_policy) 
config.set_authorization_policy( 
authorization_policy) 
config.set_forbidden_view(forbidden_view)
pyramid のセキュリティ機構 
I authentication_policy 
I アクセスしているユーザーが誰なのか? を判定する方法 
I authorization_policy 
I アクセスするユーザーは何ができるのか? を判定する方法
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 が 
呼び出される
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 を与えられる
ログインビュー 
@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
pyramid.security API 
I security.remember 
I authentication_policy に対して、identity(ログインユーザーな 
ど) を記録する(ログイン) 
I security.forget 
I authentication_policy に対して、identity を消去する(ログア 
ウト)
User の判定 
def authenticate(request, username, password): 
user = User.query.filter( 
User.username == username).first() 
if not user: 
return 
if not user.validate_password(password): 
return 
return user
TODOLIST アプリケーションその4 
I シングルページアプリケーションにする 
I リクエスト、レスポンスでJSON を取り扱う
pyramid のjson 対応 
I request.json_body 
I リクエストから直接json パースしたオブジェクトを受け取 
れる 
I json レンダラー 
I ビューが返すdict をjson にダンプしてくれる 
I オブジェクトが__json__ メソッドを持っているとダンプ中 
に呼び出される 
I xhr プリディケーション 
I view_config でxhr=True としておくと、jquery などのajax リ 
クエストはそちらのビューが優先して呼び出される
リソースに__json__ メソッドを追加する 
class TodoListResource(object): 
... 
def __json__(self, request): 
create_task_url = self.request.route_url( 
"tasks", todolist_id=self.id) 
return dict( 
tasks=self.unfinished_tasks, 
description=self.description, 
create_task_url=create_task_url)
colander でバリデーション 
@view_config(route_name="tasks", 
permission="task.create", 
renderer="json", 
xhr=True) 
def create_task(context, request): 
schema = TaskSchema() 
values = request.json_body 
values = schema.deserialize(values) 
task = context.add_task(name=values["name"]) 
return dict(task=task)
結局リソースとは 
I ビューとモデルの緩衝材 
I アプリケーションモデル 
I appstruct, __json__, __acl__ などフレームワークへのイン 
ターフェイスを提供する 
I アダプターパターン 
I すべてをリソースでやろうとしないように 
I なんでもありになりがち 
I コンストラクタで受け取った以上のオブジェクトを扱わない 
こと
まとめ 
I Pyramid はとても簡単 
I 強力なライブラリを活用できる 
I JSON アプリケーションのバックエンドとしても優秀 
I SQLAlchemy は、がんばって勉強してください
参考文献 
I Defending Pyramid’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/

Weitere ähnliche Inhalte

Was ist angesagt?

Attentionの基礎からTransformerの入門まで
Attentionの基礎からTransformerの入門までAttentionの基礎からTransformerの入門まで
Attentionの基礎からTransformerの入門までAGIRobots
 
[DL輪読会]Model-Based Reinforcement Learning via Meta-Policy Optimization
[DL輪読会]Model-Based Reinforcement Learning via Meta-Policy Optimization[DL輪読会]Model-Based Reinforcement Learning via Meta-Policy Optimization
[DL輪読会]Model-Based Reinforcement Learning via Meta-Policy OptimizationDeep Learning JP
 
第六回全日本コンピュータビジョン勉強会資料 UniT (旧題: Transformer is all you need)
第六回全日本コンピュータビジョン勉強会資料 UniT (旧題: Transformer is all you need)第六回全日本コンピュータビジョン勉強会資料 UniT (旧題: Transformer is all you need)
第六回全日本コンピュータビジョン勉強会資料 UniT (旧題: Transformer is all you need)Yasunori Ozaki
 
Neo4j Spatial - Backing a GIS with a true graph database
Neo4j Spatial - Backing a GIS with a true graph databaseNeo4j Spatial - Backing a GIS with a true graph database
Neo4j Spatial - Backing a GIS with a true graph databaseCraig Taverner
 
CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編
CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編
CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編Fixstars Corporation
 
グラフニューラルネットワーク入門
グラフニューラルネットワーク入門グラフニューラルネットワーク入門
グラフニューラルネットワーク入門ryosuke-kojima
 
『モビリティ・インテリジェンス』の社会実装 [DeNA TechCon 2019]
『モビリティ・インテリジェンス』の社会実装 [DeNA TechCon 2019]『モビリティ・インテリジェンス』の社会実装 [DeNA TechCon 2019]
『モビリティ・インテリジェンス』の社会実装 [DeNA TechCon 2019]DeNA
 
Hyperoptとその周辺について
Hyperoptとその周辺についてHyperoptとその周辺について
Hyperoptとその周辺についてKeisuke Hosaka
 
データ解析3 最適化の復習
データ解析3 最適化の復習データ解析3 最適化の復習
データ解析3 最適化の復習Hirotaka Hachiya
 
第11回 全日本コンピュータビジョン勉強会(前編)_TableFormer_carnavi.pdf
第11回 全日本コンピュータビジョン勉強会(前編)_TableFormer_carnavi.pdf第11回 全日本コンピュータビジョン勉強会(前編)_TableFormer_carnavi.pdf
第11回 全日本コンピュータビジョン勉強会(前編)_TableFormer_carnavi.pdfRyoKawanami
 
データサイエンス講義 第4章 スパムフィルタ、単純ベイズ、データラングリング
データサイエンス講義 第4章  スパムフィルタ、単純ベイズ、データラングリングデータサイエンス講義 第4章  スパムフィルタ、単純ベイズ、データラングリング
データサイエンス講義 第4章 スパムフィルタ、単純ベイズ、データラングリングtatsuyasakaeeda
 
AIと代数幾何 ~8分版~/ Artifical Inteligence Parameter Space Transformation using Alg...
AIと代数幾何 ~8分版~/ Artifical Inteligence Parameter Space Transformation using Alg...AIと代数幾何 ~8分版~/ Artifical Inteligence Parameter Space Transformation using Alg...
AIと代数幾何 ~8分版~/ Artifical Inteligence Parameter Space Transformation using Alg...Haruka Matsuzaki
 
NVIDIA Jetson導入事例ご紹介
NVIDIA Jetson導入事例ご紹介NVIDIA Jetson導入事例ご紹介
NVIDIA Jetson導入事例ご紹介NVIDIA Japan
 
[論文紹介] Understanding and improving transformer from a multi particle dynamic ...
[論文紹介] Understanding and improving transformer from a multi particle dynamic ...[論文紹介] Understanding and improving transformer from a multi particle dynamic ...
[論文紹介] Understanding and improving transformer from a multi particle dynamic ...Makoto Takenaka
 
データテクノロジースペシャル:Yahoo! JAPANにおけるメタデータ管理の試み
データテクノロジースペシャル:Yahoo! JAPANにおけるメタデータ管理の試みデータテクノロジースペシャル:Yahoo! JAPANにおけるメタデータ管理の試み
データテクノロジースペシャル:Yahoo! JAPANにおけるメタデータ管理の試みYahoo!デベロッパーネットワーク
 
Kaggle Santa 2019で学ぶMIP最適化入門
Kaggle Santa 2019で学ぶMIP最適化入門Kaggle Santa 2019で学ぶMIP最適化入門
Kaggle Santa 2019で学ぶMIP最適化入門Takami Sato
 
人と人の相性を考慮したシフトスケジューラ
人と人の相性を考慮したシフトスケジューラ人と人の相性を考慮したシフトスケジューラ
人と人の相性を考慮したシフトスケジューラ鈴木 庸氏
 
[DL輪読会]“Highly accurate protein structure prediction with AlphaFold”
[DL輪読会]“Highly accurate protein structure prediction with AlphaFold”[DL輪読会]“Highly accurate protein structure prediction with AlphaFold”
[DL輪読会]“Highly accurate protein structure prediction with AlphaFold”Deep Learning JP
 
안.전.제.일. 강화학습!
안.전.제.일. 강화학습!안.전.제.일. 강화학습!
안.전.제.일. 강화학습!Dongmin Lee
 

Was ist angesagt? (20)

Attentionの基礎からTransformerの入門まで
Attentionの基礎からTransformerの入門までAttentionの基礎からTransformerの入門まで
Attentionの基礎からTransformerの入門まで
 
[DL輪読会]Model-Based Reinforcement Learning via Meta-Policy Optimization
[DL輪読会]Model-Based Reinforcement Learning via Meta-Policy Optimization[DL輪読会]Model-Based Reinforcement Learning via Meta-Policy Optimization
[DL輪読会]Model-Based Reinforcement Learning via Meta-Policy Optimization
 
第六回全日本コンピュータビジョン勉強会資料 UniT (旧題: Transformer is all you need)
第六回全日本コンピュータビジョン勉強会資料 UniT (旧題: Transformer is all you need)第六回全日本コンピュータビジョン勉強会資料 UniT (旧題: Transformer is all you need)
第六回全日本コンピュータビジョン勉強会資料 UniT (旧題: Transformer is all you need)
 
Neo4j Spatial - Backing a GIS with a true graph database
Neo4j Spatial - Backing a GIS with a true graph databaseNeo4j Spatial - Backing a GIS with a true graph database
Neo4j Spatial - Backing a GIS with a true graph database
 
CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編
CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編
CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編
 
グラフニューラルネットワーク入門
グラフニューラルネットワーク入門グラフニューラルネットワーク入門
グラフニューラルネットワーク入門
 
『モビリティ・インテリジェンス』の社会実装 [DeNA TechCon 2019]
『モビリティ・インテリジェンス』の社会実装 [DeNA TechCon 2019]『モビリティ・インテリジェンス』の社会実装 [DeNA TechCon 2019]
『モビリティ・インテリジェンス』の社会実装 [DeNA TechCon 2019]
 
Hyperoptとその周辺について
Hyperoptとその周辺についてHyperoptとその周辺について
Hyperoptとその周辺について
 
データ解析3 最適化の復習
データ解析3 最適化の復習データ解析3 最適化の復習
データ解析3 最適化の復習
 
第11回 全日本コンピュータビジョン勉強会(前編)_TableFormer_carnavi.pdf
第11回 全日本コンピュータビジョン勉強会(前編)_TableFormer_carnavi.pdf第11回 全日本コンピュータビジョン勉強会(前編)_TableFormer_carnavi.pdf
第11回 全日本コンピュータビジョン勉強会(前編)_TableFormer_carnavi.pdf
 
データサイエンス講義 第4章 スパムフィルタ、単純ベイズ、データラングリング
データサイエンス講義 第4章  スパムフィルタ、単純ベイズ、データラングリングデータサイエンス講義 第4章  スパムフィルタ、単純ベイズ、データラングリング
データサイエンス講義 第4章 スパムフィルタ、単純ベイズ、データラングリング
 
AIと代数幾何 ~8分版~/ Artifical Inteligence Parameter Space Transformation using Alg...
AIと代数幾何 ~8分版~/ Artifical Inteligence Parameter Space Transformation using Alg...AIと代数幾何 ~8分版~/ Artifical Inteligence Parameter Space Transformation using Alg...
AIと代数幾何 ~8分版~/ Artifical Inteligence Parameter Space Transformation using Alg...
 
NVIDIA Jetson導入事例ご紹介
NVIDIA Jetson導入事例ご紹介NVIDIA Jetson導入事例ご紹介
NVIDIA Jetson導入事例ご紹介
 
[論文紹介] Understanding and improving transformer from a multi particle dynamic ...
[論文紹介] Understanding and improving transformer from a multi particle dynamic ...[論文紹介] Understanding and improving transformer from a multi particle dynamic ...
[論文紹介] Understanding and improving transformer from a multi particle dynamic ...
 
データテクノロジースペシャル:Yahoo! JAPANにおけるメタデータ管理の試み
データテクノロジースペシャル:Yahoo! JAPANにおけるメタデータ管理の試みデータテクノロジースペシャル:Yahoo! JAPANにおけるメタデータ管理の試み
データテクノロジースペシャル:Yahoo! JAPANにおけるメタデータ管理の試み
 
Kaggle Santa 2019で学ぶMIP最適化入門
Kaggle Santa 2019で学ぶMIP最適化入門Kaggle Santa 2019で学ぶMIP最適化入門
Kaggle Santa 2019で学ぶMIP最適化入門
 
人と人の相性を考慮したシフトスケジューラ
人と人の相性を考慮したシフトスケジューラ人と人の相性を考慮したシフトスケジューラ
人と人の相性を考慮したシフトスケジューラ
 
ACPC 2018 Day3 G: 回文部分列 (Palindromic Subsequences)
ACPC 2018 Day3 G: 回文部分列 (Palindromic Subsequences)ACPC 2018 Day3 G: 回文部分列 (Palindromic Subsequences)
ACPC 2018 Day3 G: 回文部分列 (Palindromic Subsequences)
 
[DL輪読会]“Highly accurate protein structure prediction with AlphaFold”
[DL輪読会]“Highly accurate protein structure prediction with AlphaFold”[DL輪読会]“Highly accurate protein structure prediction with AlphaFold”
[DL輪読会]“Highly accurate protein structure prediction with AlphaFold”
 
안.전.제.일. 강화학습!
안.전.제.일. 강화학습!안.전.제.일. 강화학습!
안.전.제.일. 강화학습!
 

Ähnlich wie Pyramid入門

自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた
自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた
自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみたYuki Takei
 
速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-Kazunari Hara
 
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方Alfresco勉強会20120829: やさしいShareダッシュレットの作り方
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方linzhixing
 
Mojoliciousをウェブ制作現場で使ってみてる
Mojoliciousをウェブ制作現場で使ってみてるMojoliciousをウェブ制作現場で使ってみてる
Mojoliciousをウェブ制作現場で使ってみてるjamadam
 
<第1回>Laravelハンズオンセミナー
<第1回>Laravelハンズオンセミナー<第1回>Laravelハンズオンセミナー
<第1回>LaravelハンズオンセミナーTatsuyoshi Mashiko
 
OSSから学ぶSwift実践テクニック
OSSから学ぶSwift実践テクニックOSSから学ぶSwift実践テクニック
OSSから学ぶSwift実践テクニック庸介 高橋
 
[東京] JapanSharePointGroup 勉強会 #2
[東京] JapanSharePointGroup 勉強会 #2[東京] JapanSharePointGroup 勉強会 #2
[東京] JapanSharePointGroup 勉強会 #2Atsuo Yamasaki
 
初めての Data api
初めての Data api初めての Data api
初めての Data apiYuji Takayama
 
Ruby on Rails の規約
Ruby on Rails の規約Ruby on Rails の規約
Ruby on Rails の規約Shuhei Iitsuka
 
Best practice laravel
Best practice laravelBest practice laravel
Best practice laravelRisa Ohnishi
 
Functional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.jsFunctional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.jsShogo Sensui
 
WordBench京都12月、WordCampUSからのWP REST APIな話
WordBench京都12月、WordCampUSからのWP REST APIな話WordBench京都12月、WordCampUSからのWP REST APIな話
WordBench京都12月、WordCampUSからのWP REST APIな話Hidetaka Okamoto
 
「Windows 8 ストア アプリ開発 tips」 hokuriku.net vol.11 (2013年1月26日)
「Windows 8 ストア アプリ開発 tips」  hokuriku.net vol.11 (2013年1月26日)「Windows 8 ストア アプリ開発 tips」  hokuriku.net vol.11 (2013年1月26日)
「Windows 8 ストア アプリ開発 tips」 hokuriku.net vol.11 (2013年1月26日)Fujio Kojima
 
Rails3.1rc4を試してみた
Rails3.1rc4を試してみたRails3.1rc4を試してみた
Rails3.1rc4を試してみたTakahiro Hidaka
 
Rails Controller Fundamentals
Rails Controller FundamentalsRails Controller Fundamentals
Rails Controller FundamentalsTakashi SAKAGUCHI
 
10分でわかるFuelPHP @ 2012/05 OSC2012 Nagoya
 10分でわかるFuelPHP @ 2012/05 OSC2012 Nagoya 10分でわかるFuelPHP @ 2012/05 OSC2012 Nagoya
10分でわかるFuelPHP @ 2012/05 OSC2012 Nagoyakenjis
 
10分でわかるFuelPHP @ 2013/04 FuelPHP入門ハンズオン vol.1
 10分でわかるFuelPHP @ 2013/04 FuelPHP入門ハンズオン vol.1 10分でわかるFuelPHP @ 2013/04 FuelPHP入門ハンズオン vol.1
10分でわかるFuelPHP @ 2013/04 FuelPHP入門ハンズオン vol.1kenjis
 

Ähnlich wie Pyramid入門 (20)

自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた
自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた
自作node.jsフレームワークとnginxを使ってラジオサイトを作ってみた
 
速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-
 
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方Alfresco勉強会20120829: やさしいShareダッシュレットの作り方
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方
 
Mojoliciousをウェブ制作現場で使ってみてる
Mojoliciousをウェブ制作現場で使ってみてるMojoliciousをウェブ制作現場で使ってみてる
Mojoliciousをウェブ制作現場で使ってみてる
 
<第1回>Laravelハンズオンセミナー
<第1回>Laravelハンズオンセミナー<第1回>Laravelハンズオンセミナー
<第1回>Laravelハンズオンセミナー
 
OSSから学ぶSwift実践テクニック
OSSから学ぶSwift実践テクニックOSSから学ぶSwift実践テクニック
OSSから学ぶSwift実践テクニック
 
[東京] JapanSharePointGroup 勉強会 #2
[東京] JapanSharePointGroup 勉強会 #2[東京] JapanSharePointGroup 勉強会 #2
[東京] JapanSharePointGroup 勉強会 #2
 
初めての Data api
初めての Data api初めての Data api
初めての Data api
 
Teclab3
Teclab3Teclab3
Teclab3
 
Ruby on Rails の規約
Ruby on Rails の規約Ruby on Rails の規約
Ruby on Rails の規約
 
Best practice laravel
Best practice laravelBest practice laravel
Best practice laravel
 
Functional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.jsFunctional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.js
 
WordBench京都12月、WordCampUSからのWP REST APIな話
WordBench京都12月、WordCampUSからのWP REST APIな話WordBench京都12月、WordCampUSからのWP REST APIな話
WordBench京都12月、WordCampUSからのWP REST APIな話
 
「Windows 8 ストア アプリ開発 tips」 hokuriku.net vol.11 (2013年1月26日)
「Windows 8 ストア アプリ開発 tips」  hokuriku.net vol.11 (2013年1月26日)「Windows 8 ストア アプリ開発 tips」  hokuriku.net vol.11 (2013年1月26日)
「Windows 8 ストア アプリ開発 tips」 hokuriku.net vol.11 (2013年1月26日)
 
Rails3.1rc4を試してみた
Rails3.1rc4を試してみたRails3.1rc4を試してみた
Rails3.1rc4を試してみた
 
Rails Controller Fundamentals
Rails Controller FundamentalsRails Controller Fundamentals
Rails Controller Fundamentals
 
Project lambda
Project lambdaProject lambda
Project lambda
 
10分でわかるFuelPHP @ 2012/05 OSC2012 Nagoya
 10分でわかるFuelPHP @ 2012/05 OSC2012 Nagoya 10分でわかるFuelPHP @ 2012/05 OSC2012 Nagoya
10分でわかるFuelPHP @ 2012/05 OSC2012 Nagoya
 
10分でわかるFuelPHP @ 2013/04 FuelPHP入門ハンズオン vol.1
 10分でわかるFuelPHP @ 2013/04 FuelPHP入門ハンズオン vol.1 10分でわかるFuelPHP @ 2013/04 FuelPHP入門ハンズオン vol.1
10分でわかるFuelPHP @ 2013/04 FuelPHP入門ハンズオン vol.1
 
Silex入門
Silex入門Silex入門
Silex入門
 

Mehr von Atsushi Odagiri

みんなのPython勉強会#77 パッケージングしよう
みんなのPython勉強会#77 パッケージングしようみんなのPython勉強会#77 パッケージングしよう
みんなのPython勉強会#77 パッケージングしようAtsushi Odagiri
 
async/await の向こう側 PyCon Kyushu 2022
async/await の向こう側 PyCon Kyushu 2022async/await の向こう側 PyCon Kyushu 2022
async/await の向こう側 PyCon Kyushu 2022Atsushi Odagiri
 
パッケージングの呼び声 Python Charity Talks in Japan 2021.02
パッケージングの呼び声 Python Charity Talks in Japan 2021.02パッケージングの呼び声 Python Charity Talks in Japan 2021.02
パッケージングの呼び声 Python Charity Talks in Japan 2021.02Atsushi Odagiri
 
eggとはなんだったのか 栄光のsetuptools
eggとはなんだったのか 栄光のsetuptoolseggとはなんだったのか 栄光のsetuptools
eggとはなんだったのか 栄光のsetuptoolsAtsushi Odagiri
 
pyconjp 2019 LT 今日のsetuptools
pyconjp 2019 LT 今日のsetuptoolspyconjp 2019 LT 今日のsetuptools
pyconjp 2019 LT 今日のsetuptoolsAtsushi Odagiri
 
Pythonでの開発を効率的に進めるためのツール設定
Pythonでの開発を効率的に進めるためのツール設定Pythonでの開発を効率的に進めるためのツール設定
Pythonでの開発を効率的に進めるためのツール設定Atsushi Odagiri
 
Pythonとパッケージングと私
Pythonとパッケージングと私Pythonとパッケージングと私
Pythonとパッケージングと私Atsushi Odagiri
 
Python3 移行への軌跡
Python3 移行への軌跡Python3 移行への軌跡
Python3 移行への軌跡Atsushi Odagiri
 
パッケージングを支える技術 pyconjp2016
パッケージングを支える技術 pyconjp2016パッケージングを支える技術 pyconjp2016
パッケージングを支える技術 pyconjp2016Atsushi Odagiri
 
Sqlalchemy sqlの錬金術
Sqlalchemy  sqlの錬金術Sqlalchemy  sqlの錬金術
Sqlalchemy sqlの錬金術Atsushi Odagiri
 
パッケージングの今
パッケージングの今パッケージングの今
パッケージングの今Atsushi Odagiri
 
パッケージングの今と未来
パッケージングの今と未来パッケージングの今と未来
パッケージングの今と未来Atsushi Odagiri
 
パッケージングの今と未来
パッケージングの今と未来パッケージングの今と未来
パッケージングの今と未来Atsushi Odagiri
 
Pyconjp2012 memory-of-europython
Pyconjp2012 memory-of-europythonPyconjp2012 memory-of-europython
Pyconjp2012 memory-of-europythonAtsushi Odagiri
 
What makes pyramid unique
What makes pyramid uniqueWhat makes pyramid unique
What makes pyramid uniqueAtsushi Odagiri
 
エキPy lt repoze.whoの紹介
エキPy lt repoze.whoの紹介エキPy lt repoze.whoの紹介
エキPy lt repoze.whoの紹介Atsushi Odagiri
 

Mehr von Atsushi Odagiri (20)

みんなのPython勉強会#77 パッケージングしよう
みんなのPython勉強会#77 パッケージングしようみんなのPython勉強会#77 パッケージングしよう
みんなのPython勉強会#77 パッケージングしよう
 
async/await の向こう側 PyCon Kyushu 2022
async/await の向こう側 PyCon Kyushu 2022async/await の向こう側 PyCon Kyushu 2022
async/await の向こう側 PyCon Kyushu 2022
 
パッケージングの呼び声 Python Charity Talks in Japan 2021.02
パッケージングの呼び声 Python Charity Talks in Japan 2021.02パッケージングの呼び声 Python Charity Talks in Japan 2021.02
パッケージングの呼び声 Python Charity Talks in Japan 2021.02
 
eggとはなんだったのか 栄光のsetuptools
eggとはなんだったのか 栄光のsetuptoolseggとはなんだったのか 栄光のsetuptools
eggとはなんだったのか 栄光のsetuptools
 
pyconjp 2019 LT 今日のsetuptools
pyconjp 2019 LT 今日のsetuptoolspyconjp 2019 LT 今日のsetuptools
pyconjp 2019 LT 今日のsetuptools
 
Pythonでの開発を効率的に進めるためのツール設定
Pythonでの開発を効率的に進めるためのツール設定Pythonでの開発を効率的に進めるためのツール設定
Pythonでの開発を効率的に進めるためのツール設定
 
Pythonとパッケージングと私
Pythonとパッケージングと私Pythonとパッケージングと私
Pythonとパッケージングと私
 
Python3 移行への軌跡
Python3 移行への軌跡Python3 移行への軌跡
Python3 移行への軌跡
 
パッケージングを支える技術 pyconjp2016
パッケージングを支える技術 pyconjp2016パッケージングを支える技術 pyconjp2016
パッケージングを支える技術 pyconjp2016
 
Sqlalchemy sqlの錬金術
Sqlalchemy  sqlの錬金術Sqlalchemy  sqlの錬金術
Sqlalchemy sqlの錬金術
 
Clack meetup #1 lt
Clack meetup #1 ltClack meetup #1 lt
Clack meetup #1 lt
 
パッケージングの今
パッケージングの今パッケージングの今
パッケージングの今
 
パッケージングの今と未来
パッケージングの今と未来パッケージングの今と未来
パッケージングの今と未来
 
パッケージングの今と未来
パッケージングの今と未来パッケージングの今と未来
パッケージングの今と未来
 
Bplt11 form alchemy
Bplt11 form alchemyBplt11 form alchemy
Bplt11 form alchemy
 
Python3でwebアプリ
Python3でwebアプリPython3でwebアプリ
Python3でwebアプリ
 
Pyconjp2012 memory-of-europython
Pyconjp2012 memory-of-europythonPyconjp2012 memory-of-europython
Pyconjp2012 memory-of-europython
 
What makes pyramid unique
What makes pyramid uniqueWhat makes pyramid unique
What makes pyramid unique
 
エキPy lt repoze.whoの紹介
エキPy lt repoze.whoの紹介エキPy lt repoze.whoの紹介
エキPy lt repoze.whoの紹介
 
World plonedaylt
World plonedayltWorld plonedaylt
World plonedaylt
 

Pyramid入門

  • 1. Pyramid 入門 aodag September 15, 2014
  • 2. お前誰よ 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 の歴史 I repoze.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 from pyramid.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 I config.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 を使う pip install 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
  • 11. Route の登録 I add_route # タスク一覧、タスク作成 config.add_route("top", "/") # タスク削除 config.add_route( "task_finish", "/tasks/{task_id}/finish")
  • 12. ビュー:タスク一覧 @view_config(route_name="top", request_method="GET", renderer="templates/index.mako") def index(request): tasks = Task.query.all() return dict(tasks=tasks) I route_name I request_method I renderer
  • 13. ビュー:タスク作成 @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 で使えるテンプレート I Pyramid1.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 install pyramid_mako config.include("pyramid_mako") I pyramid_mako I mako テンプレートを使ったrenderer I include すると“.mako” 拡張子で指定したレンダラーでmako テンプレートを利用できる
  • 17. テンプレート:タスク一覧 <ul> %for task in tasks: <li> ${task.name} <form action="${request.route_url('task_finish', task_id=task.id)}" method="post"> <button type="submit">Finish</button> </form> </li> %endfor </ul>
  • 18. テンプレート:タスク作成フォーム <form action="${request.route_url('top')}" method="post"> <input type="text" name="name"> <button type="submit">Add</button> </form>
  • 20. TODOLIST アプリケーションその2 I Route と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
  • 23. resource factory def task_factory(request): todolist_id = request.matchdict["todolist_id"] task_id = request.matchdict["task_id"] task = Task.query.filter( Task.id == task_id, Task.todolist_id == todolist_id).first() if taks is None: raise HTTPNotFound return TaskResource(task, request)
  • 24. アダプター class TaskResource(object): def __init__(self, task, request): self.task = task self.request = request def finish(self): self.task.finish() @property def todolist_url(self): return self.request.route_url( "todolist", todolist_id=self.task.todolist_id) I task ラップする対象 I request API 呼び出しのために必要
  • 25. view @view_config( route_name="task", name="finish", context=".reources.TaskResource", request_method="POST") def task_finish(context, request): context.finish() return HTTPFound(location=context.todolist_url) I view はコンテキストにイベントを伝える(メソッドを呼び出 す)だけ
  • 26. ビューが呼び出されるまで 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 でフォーム作成 I Colander I スキーマ、バリデーションライブラリ I Deform I フォームライブラリ I Peppercorn I HTML フォームで構造化したデータを扱うためのパーサー
  • 28. Deform/Colander/peppercorn の動作 I appstruct, pstruct, cstruct I アプリケーションモデルなどをappstruct にして渡す I deform がappstruct をフォームウィジェットとともにHTML にする I ブラウザからsubmit されるとパラメータはpstruct で渡され てくる I peppercoron でpstruct をcstruct に変換 I colander でcstruct をappstruct に変換
  • 29. Colander スキーマ import colander 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 抽象的なスキーマ情報にこういう詳細が入るのはちょっとや だ(´・ω・`)
  • 30. pyramid_deform @view_config(....) class TodolistForm(FormView): schema = TodolistSchema() buttons = ('save',) @property def context(self): return self.request.context def save_success(self, values): todolist = self.context.add_todolist(**values) return HTTPFound(todolist.url) I FormView を継承してビューを実装する I schema でcolander スキーマを指定 I buttons でボタンの名前(‘save’) を設定しておくと、対応する メソッド(save_success) がバリデーション後に呼び出される
  • 31. フォームのデフォルト値 class EditTodolistForm(FormView): schema = TodolistSchema() buttons = ('save',) @property def context(self): return self.request.context def apptsruct(self): return self.context.appstruct() def save_success(self, values): todolist = self.context todolist.update(**values) return HTTPFound(todolist.url)
  • 32. 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>
  • 36. Asset Specification I “{package}:{directory}” のような文字列でパッケージ以下 のディレクトリを表す I my.todolist:static は os.path.join(os.path.dirname(my.todolist.__file__), “static”) で取得できるディレクトリ
  • 37. ベーステンプレート <html> <head> <link rel="stylesheet" href="${request.static_url( 'deform:static/css/bootstramp.min.css')}"> <%block name="extra_header"></%block> </head> <body> <div class="container"> ${next.body()} </div> </body> </html>
  • 38. テンプレート <%inherit file="base.mako"> <%block name="extra_header> %for reqt in css_links: <link rel="stylesheet" href="${request.static_url(reqt)}" type="text/css" /> %endfor ... </%block>
  • 39. Mako テンプレート I block タグ I あとから継承先のテンプレートで埋める場所 I next.body() I 直接継承しているテンプレートの内容をレンダリングする I レイアウトなど多段に継承するときに必要 I inherit タグ I 継承テンプレートを指定 I %for, %if, %while など I Python の各種制御構文と同じ I インデントブロックじゃないので、%endfor などが必要
  • 40. TODOLIST アプリケーションその3 I User モデルを追加 I 認証、権限を追加
  • 41. security def includeme(config): secret = config.registry.settings['session.secret'] session_factory = SignedCookieSessionFactory( secret=secret) config.set_session_factory(session_factory) authentication_policy = SessionAuthenticationPolicy() authorization_policy = ACLAuthorizationPolicy() config.set_authentication_policy( authentication_policy) config.set_authorization_policy( authorization_policy) config.set_forbidden_view(forbidden_view)
  • 42. pyramid のセキュリティ機構 I authentication_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 I security.remember I authentication_policy に対して、identity(ログインユーザーな ど) を記録する(ログイン) I security.forget I authentication_policy に対して、identity を消去する(ログア ウト)
  • 47. User の判定 def authenticate(request, username, password): user = User.query.filter( User.username == username).first() if not user: return if not user.validate_password(password): return return user
  • 48. TODOLIST アプリケーションその4 I シングルページアプリケーションにする I リクエスト、レスポンスでJSON を取り扱う
  • 49. pyramid のjson 対応 I request.json_body I リクエストから直接json パースしたオブジェクトを受け取 れる I json レンダラー I ビューが返すdict をjson にダンプしてくれる I オブジェクトが__json__ メソッドを持っているとダンプ中 に呼び出される I xhr プリディケーション I view_config でxhr=True としておくと、jquery などのajax リ クエストはそちらのビューが優先して呼び出される
  • 50. リソースに__json__ メソッドを追加する class TodoListResource(object): ... def __json__(self, request): create_task_url = self.request.route_url( "tasks", todolist_id=self.id) return dict( tasks=self.unfinished_tasks, description=self.description, create_task_url=create_task_url)
  • 51. colander でバリデーション @view_config(route_name="tasks", permission="task.create", renderer="json", xhr=True) def create_task(context, request): schema = TaskSchema() values = request.json_body values = schema.deserialize(values) task = context.add_task(name=values["name"]) return dict(task=task)
  • 52. 結局リソースとは I ビューとモデルの緩衝材 I アプリケーションモデル I appstruct, __json__, __acl__ などフレームワークへのイン ターフェイスを提供する I アダプターパターン I すべてをリソースでやろうとしないように I なんでもありになりがち I コンストラクタで受け取った以上のオブジェクトを扱わない こと
  • 53. まとめ I Pyramid はとても簡単 I 強力なライブラリを活用できる I JSON アプリケーションのバックエンドとしても優秀 I SQLAlchemy は、がんばって勉強してください
  • 54. 参考文献 I Defending Pyramid’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/