ビュー¶
Pyramid の重要な仕事のうちの一つは、 request が アプリケーションに達したときに view callable を見つけて起動する ことです。ビュー callable は、あなたのアプリケーションになされたリクエスト に応じて興味深いことを行うコードの断片です。それらはあらゆる面白いウェブ アプリケーションの「肉(本質、芯)」です。
Note
Pyramid view callable は、会話での省略表現でしばしば view と呼ばれます。しかし、ビュー 設定 とビュー callable を実装するコード、およびビュー 検索 プロセスの間に著しい違いがあるので、 このドキュメンテーションでは、それほど曖昧でない用語を使用する必要が あります。
本章では、ビュー callable をどのように定義するかを説明します。実際に どのようにして特定の URL パターンおよび他のリクエスト状況に対してビュー callable を接続するように Pyramid に伝えるかを理解するためには、 次章 (View Configuration) まで待たなければなりません。
ビュー callable¶
ビュー callable は、自明のことのように聞こえる危険を冒せば、 callable な
Python オブジェクトです。具体的には、ビュー callable は、関数、クラス、または
__call__
メソッド (これによりインスタンスが呼び出し可能になります) を
実装したインスタンスです。
ビュー callable は、最低限 request
という名前の単一の引数を受け取る
必要があります。この引数は Pyramid Request オブジェクトを
表わします。 request オブジェクトは、上流の WSGI サーバーによって
Pyramid に提供される WSGI 環境変数を表わします。
予想されるように、 request オブジェクトは実行中の特定の HTTP リクエストに
関してアプリケーションが知る必要のあるすべてのものを含んでいます。
ビュー callable の最終責任は Pyramid
Response オブジェクト
を生成することです。これは、ビュー callable コード内で Response
オブジェクトを生成してそれを直接返すか、あるいはビュー callable の本体
内部から特別な種類の例外を上げることによって行うことができます。
ビュー callable を関数として定義する¶
ビュー callable を定義する最も簡単な方法のうちの一つは、 request
という名前の単一の引数を受け取り、 Response オブジェクトを返す
関数を作成することです。例えば、これは関数として実装された “hello world”
ビュー callable です:
1 2 3 4 | from pyramid.response import Response
def hello_world(request):
return Response('Hello world!')
|
ビュー callable をクラスとして定義する¶
ビュー callable は関数の代わりに Python クラスによっても表すことができます。
ビュー callable がクラスである場合、それが関数または別の非クラスの callable
である場合とは呼び出しのセマンティクスがやや異なります。ビュー callable
がクラスである場合、クラスの __init__
メソッドが request
パラメータ
を伴って呼ばれます。その結果、クラスのインスタンスが生成されます。続いて、
そのインスタンスの __call__
メソッドがパラメータなしで起動されます。
クラスとして定義されたビューには次のような特性がなければなりません:
request
引数を受け取る__init__
メソッド。
- パラメータを受け取らず、レスポンスを返す
__call__
(あるいは他の) メソッド。
例えば:
1 2 3 4 5 6 7 8 | from pyramid.response import Response
class MyView(object):
def __init__(self, request):
self.request = request
def __call__(self):
return Response('hello')
|
__init__
に渡された request オブジェクトは ビュー callable を関数として定義する
で述べたのと同じ型の request オブジェクトです。
レスポンスを返すことが期待されるメソッドを表わすために __call__
と
は別の属性を使用したければ、ビュー設定の一部として attr
値を使用する
ことができます。 View Configuration Parameters を参照してください。
クラスが関連するビュー callable のコレクションを表わすようにしたければ、
各々クラスの異なるメソッドを指す異なる attr 値を用いて、同じビュー
callable クラスを異なるビュー設定の中で使用することができます。
ビュー callable レスポンス¶
ビュー callable は、 Pyramid Response インタフェースを
実装するオブジェクトを返すことができます。 Response インタフェース
を実装するものを返す最も簡単な方法は、
pyramid.response.Response
オブジェクトのインスタンスを直接
返すことです。例えば:
1 2 3 4 | from pyramid.response import Response
def view(request):
return Response('OK')
|
Pyramid は、 pyramid.response.Response
を継承する一連の
様々な「例外」クラスを提供しています。例えば、クラス
pyramid.httpexceptions.HTTPFound
のインスタンスは
Response
を継承するので、これも有効な
response オブジェクトです。例については、 HTTP 例外 と
HTTP リダイレクトを行うためにビュー callable を使う を参照してください。
Note
様々な状況で pyramid.response.Response
のインスタンスでない
オブジェクトをビュー callable から返すこともできます。
これはテストを書くときや複数のビュー callable の間でコードを共有しようと
するときに有用なことがあります。これを可能にする通常の方法については
レンダラー を参照してください。それよりもまれな、
ビュー callable が Response オブジェクト以外を返すことを可能にする方法は
Pyramid がビューレスポンスを扱う方法の変更 の中で文書化されます。
ビュー callable の中で特別な例外を使用する¶
通常、ビュー callable 内で Python 例外が上がった場合、 Pyramid は アプリケーションを起動した WSGI サーバまで例外が伝搬することを 許します。例外は通常そこで捕捉されてログに記録されます。
しかし、利便性のために特別な例外のセットが存在しています。これらの例外が ビュー callable 内で上がった場合、 Pyramid によって常にレスポンスが 生成されます。これらは HTTP exception オブジェクトとして知られています。
HTTP 例外¶
pyramid.httpexceptions
モジュールの中で
pyramid.httpexceptions.HTTPException
から継承すると文書化
されたすべてのクラスは http exception オブジェクトです。
HTTP 例外オブジェクトのインスタンスは、ビューコードの内部から
戻り値として返される か、または 例外として投げられ ます。
いずれの場合も、そのインスタンスはビューからのレスポンスとして
使用されます。
例えば、 pyramid.httpexceptions.HTTPUnauthorized
例外を投げる
ことができます。これは 401 Unauthorized
ステータスでレスポンスを生成
するでしょう:
1 2 3 4 | from pyramid.httpexceptions import HTTPUnauthorized
def aview(request):
raise HTTPUnauthorized()
|
HTTP 例外は raise する代わりに 返す こともできます (HTTP 例外は有効な response オブジェクトでもあります):
1 2 3 4 | from pyramid.httpexceptions import HTTPUnauthorized
def aview(request):
return HTTPUnauthorized()
|
HTTP 例外を生成するための近道は
pyramid.httpexceptions.exception_response()
関数です。この関数は、
HTTP ステータスコードを受け取り対応する HTTP 例外を返します。例えば、
HTTPUnauthorized
をインポートして
response オブジェクトを構築する代わりに、同じオブジェクトを構築して返す
ために exception_response()
関数を使用する
ことができます。
1 2 3 4 | from pyramid.httpexceptions import exception_response
def aview(request):
raise exception_response(401)
|
これは 401 が “HTTP Unauthorized” のための HTTP ステータスコードであるためです。
したがって、 raise exception_response(401)
は
raise HTTPUnauthorized()
と機能的に等価です。
pyramid.httpexceptions
の中で、各 HTTP レスポンスコードから
その目的および関連する HTTP 例外オブジェクトにマッピングする
ドキュメンテーションが提供されます。
Note
exception_response()
関数は
Pyramid 1.1 で新たに追加されました。
Pyramid は HTTP 例外をどのように使用するか¶
HTTP 例外はアプリケーション開発者が直接使うためのものです。
しかし、 Pyramid は自身も通常動作の間に様々なポイントで
2 つの HTTP 例外を上げます: pyramid.httpexceptions.HTTPNotFound
と
pyramid.httpexceptions.HTTPForbidden
です。
リクエストをサービスするビューが見つからない場合、 Pyramid は
HTTPNotFound
例外を上げます。
認可がセキュリティポリシーによって禁止された場合、 Pyramid は
Forbidden
例外を上げます。
HTTPNotFound
が Pyramid 自体によって、
またはビューコード内で上げられる場合、 Not Found View の結果が
リクエストを行なったユーザエージェントに返されます。
HTTPForbidden
が Pyramid 自体によって、
またはビューコード内で上げられる場合、 Forbidden View の結果が
リクエストを行なったユーザエージェントに返されます。
カスタム例外ビュー¶
ビュー callable の中で特別な例外を使用する に述べられているように、 HTTP 例外が投げられて専用のビューによって補足されることを可能にする機構を、 アプリケーション開発者もレスポンスの任意の例外を変換するために使用する ことができます。
特定の例外が Pyramid ビューコードから上がった場合に常に呼ばれる
ビューを登録するためには、レスポンスを生成したいビュー callable を指す
ビュー設定の context
として例外クラスあるいはその親クラスのうちの
一つを使用してください。
例えば、 helloworld.exceptions
という名前のモジュールに次のような
例外クラスがあるとします:
1 2 3 | class ValidationFailure(Exception):
def __init__(self, msg):
self.msg = msg
|
どこかにある 他の コードが helloworld.exceptions.ValidationFailure
例外を上げた場合には常に呼ばれるようにビュー callable を設定することができます:
1 2 3 4 5 6 7 8 | from pyramid.view import view_config
from helloworld.exceptions import ValidationFailure
@view_config(context=ValidationFailure)
def failed_validation(exc, request):
response = Response('Failed validation: %s' % exc.msg)
response.status_int = 500
return response
|
このビュー登録を拾い上げるために scan が実行されたとすると、
このビュー callable はアプリケーションのビューコードによって
helloworld.exceptions.ValidationFailure
が上げられる場合は常に起動
されることになります。カスタム root ファクトリ、カスタムトラバーサ、
あるいはカスタムビュー、またはルート述語によって上げられた同じ例外も
捕捉されフックされます。
他の通常のビュー述語も例外ビュー登録と組み合わせて使用できます:
1 2 3 4 5 6 7 8 | from pyramid.view import view_config
from helloworld.exceptions import ValidationFailure
@view_config(context=ValidationFailure, route_name='home')
def failed_validation(exc, request):
response = Response('Failed validation: %s' % exc.msg)
response.status_int = 500
return response
|
上記の例外ビューは route_name
に home
と指定しています。これは
ルート一致が home
という名前を持っている時にだけそれが呼ばれること
を意味しています。そのため、ある例外に対する例外ビューをシステムの中に
複数持つことが可能です: リクエスト状況のセットがビュー登録と一致する時は
「最も特殊な」ものが呼ばれます。
例外ビュー設定を行う場合、正常に使用できない唯一のビュー述語は
name
です。例外ビューを検索するために使用される名前は常に空の文字列
です。例外ビューとして登録された名前を持つビューは無視されます。
Note
Exception
から継承したコンテキストリソース型に対して登録された
通常の (つまり例外ではない) ビューは、正常に動作します。例外ビュー設定が
処理される場合、 2つの ビューが登録されます。一方は「通常の」ビュー
として、他方は「例外」ビューとして。これは、 context
として例外を
通常のビューに使用できることを意味します。
例外ビューは任意のビュー登録メカニズムで構成することができます:
@view_config
デコレータまたは命令的な add_view
スタイル。
Note
Pyramid の exception view 処理ロジックは
pyramid.tweens.excview_tween_factory()
という tween ファクトリ関数
として実装されます。 Pyramid 例外ビューの処理が期待され、
pyramid.tweens
設定で tween ファクトリが指定されている場合、
pyramid.tweens
設定リストに
pyramid.tweens.excview_tween_factory()
関数を明示的に追加
しなければなりません。それが存在しなければ、 Pyramid は例外ビューの
処理を行ないません。
HTTP リダイレクトを行うためにビュー callable を使う¶
pyramid.httpexceptions.HTTPFound
クラスを使用して HTTP
リダイレクトを発行することができます。このクラスのインスタンスを
例外として上げるか戻り値として返せば、クライアントは “302 Found”
レスポンスを受け取るでしょう。
これを行うために、 pyramid.httpexceptions.HTTPFound
インスタンス
を 返す ことができます。
1 2 3 4 | from pyramid.httpexceptions import HTTPFound
def myview(request):
return HTTPFound(location='http://example.com')
|
または、それを返す代わりに HTTPFound 例外を上げることができます。
1 2 3 4 | from pyramid.httpexceptions import HTTPFound
def myview(request):
raise HTTPFound(location='http://example.com')
|
インスタンスが例外として上げられる場合、それはデフォルト exception response ハンドラによって捕捉され、レスポンスへと変換 されます。
ビュー callable の中でフォーム送信を扱う (Unicodeと文字集合の問題)¶
ほとんどのウェブアプリケーションは、ウェブブラウザおよび様々な他の クライアントからフォーム送信を受け取る必要があります。 Pyramid では、 フォーム送信を扱うロジックは常に view の一部です。 WebOb APIを使用してフォーム送信データを処理する方法の一般的な 概要については、 Request and Response Objects と WebObドキュメンテーション内の “Query and POST variables”. を見てください。 Pyramid は、リクエストとレスポンスの実装については WebOb に任せています。また、フォーム送信データの取り扱いはリクエスト実装の 特性です。 WebOb のリクエスト API を理解することは、フォーム送信データを 処理する方法を理解するための鍵です。
Pyramid ビュー内でフォーム送信データを処理しようとする場合、
意識する必要のあるいくつかのデフォルトがあります。フォーム送信データに
上位ビットが立った (つまり非 ASCII) 文字が含まれていることは、
非常に一般的です。また、 UTF-8 符号化はウェブ上で文字データに使用される
最も一般的な符号化です。バイト文字列を扱ったり格納したりするよりも
Unicode 値の方がはるかに健全なので、 Pyramid はフォーム送信値を
可能なら UTF-8 から Unicode へ暗黙的にデコードするように WebOb
リクエスト機能を構成します。ビューコードが request.params
,
request.GET
あるいは request.POST
API によってフォームフィールド
値を得る場合、暗黙のデコードが起こります (これらの API に関する詳細に
関しては pyramid.request を参照)
Note
多くの人々が Unicode と UTF-8 の間の違いに混乱を見い出します。 Unicode は、世界の書記体系のうちのほとんどをサポートするテキストを表わす ための規格です。しかし、転送と記録のために Unicode データをバイトへ エンコードするための多くの方法があります。 UTF-8 は Unicode のための 特定の符号化で、 ASCII と後方互換性を持ちます。このため、データの 大部分が ASCII 文字であるような場合に UTF-8 はデータをエンコードする のに非常に便利です。それはウェブ上では大部分正しいです。 UTF-8 は URL のための標準文字符号化でもあります。
例として、次のようなフォームページがブラウザクライアントに表示され、
その action
が何らかの Pyramid ビューコードを指していると
仮定しましょう:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<form method="POST" action="myview">
<div>
<input type="text" name="firstname"/>
</div>
<div>
<input type="text" name="lastname"/>
</div>
<input type="submit" value="Submit"/>
</form>
</html>
|
Pyramid アプリケーション内の myview
ビューコードは、
request.params
によって返された値が str
型ではなく unicode
型になると想定 しなければなりません 。上記のフォームからフォームポスト
を受け取るのに下記のコードは動くでしょう:
1 2 3 | def myview(request):
firstname = request.params['firstname']
lastname = request.params['lastname']
|
しかし、次の myview
ビューコードは動かないかもしれません。
request.params
から取得したデコード済みの (unicode
) 値を
デコードしようとしているからです:
1 2 3 4 5 | def myview(request):
# the .decode('utf-8') will break below if there are any high-order
# characters in the firstname or lastname
firstname = request.params['firstname'].decode('utf-8')
lastname = request.params['lastname'].decode('utf-8')
|
暗黙のデコードが確実 (reliably) に動作するため、 Pyramid ビューに
ポストするすべてのフォームをレンダリングする際は必ず明示的に charset
エンコーディングを UTF-8 と定義するようにします。これは、レスポンスの
Content-Type
ヘッダの中で ;charset=UTF-8
を指定することによって、
あるいは上記のフォームのようにフォームを含むページの HTML head
で
charset が UTF-8 であることを示す meta http-equiv
タグによって
行うことができます。既知のすべてのブラウザクライアントは、フォームを
送信する際にはそのフォームを含むレスポンスの Content-Type
値によって
推測されたのと同じ文字集合を使ってフォームデータをエンコードすべきで
あると仮定するので、これは明示的に行われなければなりません。フォームデータ
をエンコードするためにどの charset を使用すべきかをブラウザクライアント
に伝える一般的に受け入れられた方法はこれ以外にありません。エンコードを
明示的に指定しなければ、ブラウザクライアントはフォームデータを送信する前に
デフォルト文字セットにエンコードすることを選択します。それはサーバーが
期待する UTF-8 ではない可能性があります。非 UTF8 charset でエンコードされた
フォームデータを含むリクエストがビューコードによって扱われるなら、いずれ
他の文字集合でエンコードされたフォームデータ内の 8 bit 文字をデコード
できずにビュー内で実行されたリクエストコードで
(例えば request.params['somename']
がアクセスされた場合に)
エラーが発生するでしょう。
レスポンスを生成するために Response
クラスを
使用しているか、あるいは render_template_
テンプレート API を使用して
いれば、 Content-Type
ヘッダーに UTF-8 charset がデフォルトとして
自動的にセットされます。明示的な charset のない Content-Type
ヘッダ
を返した場合、テキスト型のレスポンスコンテントタイプ (例えば
text/html
や application/xml
など) に対しては、あなたの代わりに
リクエスト (訳注: レスポンスの間違い?) がレンダリング時に Content-Type
ヘッダー値に ;charset=utf-8
トレーラーを加えます。独自のレスポンス
オブジェクトを使用していれば、これを自分自身で確実に行う必要があるでしょう。
Note
request.params
, request.GET
, request.POST
によって
得られるリクエスト params の 値 だけが Pyramid デフォルト設定の
もとでユニコードオブジェクトに暗黙にデコードされます。キーは、
依然として(バイト)文字列です。
ビュー callable の引数/呼び出し規約を変更する¶
通常、ビュー callable は単一の引数 request
だけを受け取ると定義されます。
しかし、その代わりにビュー callable はクラス、関数あるいは 2 つ の位置引数
を受け取る何らかの callableとして定義されることも可能です: 1つ目の引数と
して context リソース、 2 つ目の引数として request です。
このスタイルで定義されたビュー関数に渡される context と request の各引数は、以下のように定義することができます:
context
request
現在の WSGI リクエストを表わす Pyramid リクエストオブジェクト。
次のタイプがこのスタイルのビュー callable として動作します:
2つの引数
context
,request
を受け取る関数。例えば:1 2 3 4
from pyramid.response import Response def view(context, request): return Response('OK')
context, request
を受け取る__init__
メソッドと、 引数を受け取らない__call__
メソッドを持つクラス。例えば:1 2 3 4 5 6 7 8 9
from pyramid.response import Response class view(object): def __init__(self, context, request): self.context = context self.request = request def __call__(self): return Response('OK')
context,request
を受け取る__call__
メソッドを持つ 任意の callable 。例えば:1 2 3 4 5 6
from pyramid.response import Response class View(object): def __call__(self, context, request): return Response('OK') view = View() # this is the view callable
このスタイルの呼び出し規約は、コンテキストオブジェクトがビュー callable のコード自身によって頻繁に使用される traversal に基づく アプリケーションで最も有用です。
どのビュー呼び出し規約が使われていても、ビューコードは常に
request.context
によってコンテキストにアクセスする必要があります。
設定変数をビューへ渡す¶
設定 .ini ファイルからビューに変数を渡すことに関する情報は Deployment Settings を参照してください。
Pylons 1.0 スタイルの “コントローラ” ディスパッチ¶
pyramid_handlers という名のパッケージ (PyPI から利用可能) は Pylons スタイルの「コントローラ」の類似品を提供します。 それは、アプリケーションが URL dispatch を単独で使用する場合に より多くの自動化を提供する特別な種類のビュークラスです。