ビュー(Views)

Pyramid の重要な仕事のうちの一つは、 request がアプリケーションに達したときに view callable を見つけて起動することです。ビュー callable はアプリケーションになされたリクエストに応じて興味深いことを行うコードの断片です。それらはあらゆる興味深いウェブアプリケーションの「肉(本質、芯)」です。

注釈

Pyramid view callable は、会話での省略表現でしばしば view と呼ばれます。しかし、「設定」ビューと*callable*」ビューを実装するコード、および「検索」ビュー プロセスの間に著しい違いがあるので、このドキュメンテーションでは、それほど曖昧でない用語を使用する必要があります。

本章では、ビュー callable をどのように定義するかを説明します。実際にどのようにして特定の URL パターンおよび他のリクエスト状況に対してビューcallable を接続するように Pyramid に伝えるかを理解するためには、次章 ((機械翻訳) 設定を表示) まで待たなければなりません。

Callablesビュー(View Callables)

Callableビューは、明らかに呼び出し可能なPythonオブジェクトを検出する危険性があります。 具体的には、ビュー callable は、関数、クラス、または __call__ メソッド (これによりインスタンスが呼び出し可能になります) を実装したインスタンスです。

callableビューは少なくとも request という名前の単一の引数を受け取る必要があります。この引数は Pyramid Request オブジェクトを表わしています。 requestオブジェクトは、上流のWSGIサーバーによって:app:Pyramid に提供される WSGI 環境変数を表わします。ご想像の通りrequest オブジェクトは実行中の特定のHTTP リクエストに関してアプリケーションが知る必要のあるすべてのものを含んでいます。

callableビュー の最終責任は Pyramid Response オブジェクトを生成することです。これはcallableビューのコード内で Response オブジェクトを生成してそれを直接返却するか、あるいはcallableビューの本体内部から特別な種類の例外を上げることによって実行できます。

callableビューを関数として定義する(Defining a View Callable as a Function)

callableビューを定義する最も簡単な方法のうちの一つは、 request という名前の単一の引数を受け取り、 Response オブジェクトを返す関数を作成することです。例えば以下は関数として実装された 「hello world」callableビューです:

1
2
3
4
from pyramid.response import Response

def hello_world(request):
    return Response('Hello world!')

callableビューをクラスとして定義する(Defining a View Callable as a Class)

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ビューを関数として定義する(Defining a View Callable as a Function) で述べたのと同じ型の request オブジェクトです。

レスポンスを返すことが期待されるメソッドを表わすために __call__ とは別の属性を使用したければ、ビュー設定の一部として attr 値を使用するできます。 設定パラメータの表示 を参照してください。クラスが関連するcallableビュー のコレクションを表したければ、各々クラスの異なるメソッドを指す異なる attr 値を用いて同じビューcallable クラスを異なるビュー設定の中で使用できます。

callableビューレスポンス(View Callable Responses)

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 Exceptions)HTTP リダイレクトを行うためにcallableビューを使用する(Using a View Callable to do an HTTP Redirect) を参照してください。

注釈

様々な状況で pyramid.response.Response のインスタンスでないオブジェクトをcallableビューから返すこともできます。これはテストを書くときや複数のビュー callable の間でコードを共有しようとするときに有用な時があります。これを可能にする通常の方法については (機械翻訳) レンダラー を参照してください。それよりもまれな、callableビューが Response オブジェクト以外を返すことを可能にする方法は ピラミッドが応答を見る方法を変える の中で文書化されています。

callableビューの中で特別な例外を使用する(Using Special Exceptions in View Callables)

通常はPythonの例外がcallableビュー内で上がった場合は、 Pyramid は例外をアプリケーションを起動した WSGI サーバのすべてに伝搬させます。例外は通常そこで捕捉されてログに記録されます。

ただし便宜上に特別な例外のセットが存在しています。これらの例外がcallableビュー内で上がった場合、 Pyramid によって常にレスポンスが生成されます。これらは HTTP exception オブジェクトと呼ばれています。

HTTPの例外(HTTP Exceptions)

pyramid.httpexceptions.HTTPException を継承しているとして記述されているすべての pyramid.httpexceptions クラスは、 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 例外オブジェクトにマッピングするドキュメンテーションが提供されます。

バージョン 1.1 で追加: exception_response() 関数。

Pyramid は HTTP 例外をどのように使用するか(How Pyramid Uses HTTP Exceptions)

HTTP 例外はアプリケーション開発者が直接使うためのものです。しかし、 Pyramid は自身も通常動作の間に様々なポイントで2つの HTTP 例外を上げます

  • HTTPNotFound はリクエストを処理するためのビューが見つからない場合に発生します
  • HTTPForbidden はセキュリティポリシーによって許可が禁止されたときに発生します。

HTTPNotFound が Pyramid自身によって、またはビューのコード内で上げられる場合、 Not Found View の結果がリクエストを行なったユーザエージェントに返されます。

HTTPForbidden が Pyramid 自体によって、またはビューコード内で上げられる場合、 Forbidden View の結果がリクエストを行なったユーザエージェントに返されます。

カスタム例外ビュー(Custom Exception Views)

callableビューの中で特別な例外を使用する(Using Special Exceptions in View Callables) に述べられているように、 HTTP"例外が投げられて専用のビューによって補足されることを可能にする機構を、アプリケーション開発者もレスポンスの任意の例外を変換するために使用できます。

Pyramid ビューコード内から特定の例外が発生するたびに呼び出される exception view を登録するには、 pyramid.config.Configurator.add_exception_view() を使用して、例外(または例外のサブクラス)およびポイントに一致するビュー設定を登録します。リクエストを生成したいcallableなビューで呼び出せます。例外は、ビューに登録された view predicate およびビュー自体に「コンテキスト」引数として渡されます。 便宜上、新しいデコレータ pyramid.views.exception_view_config が存在していて、例外ビューを簡単に登録するために使用できます。

例えば、 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 exception_view_config
from helloworld.exceptions import ValidationFailure

@exception_view_config(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 factory、カスタムtraverser、あるいはカスタムビュー、またはルート述語によって上げられた同じ例外も捕捉されフックされます。

他の通常のビュー述語も例外ビュー登録と組み合わせて使用できます:

1
2
3
4
5
6
7
8
from pyramid.view import view_config
from helloworld.exceptions import ValidationFailure

@exception_view_config(ValidationFailure, route_name='home')
def failed_validation(exc, request):
    response =  Response('Failed validation: %s' % exc.msg)
    response.status_int = 500
    return response

上記の例外ビューは route_namehome と指定しています。これはルート一致が home という名前を持っている時にだけ呼ばれることを意味しています。そのため、ある例外に対する例外ビューをシステムの中に複数持つことが可能です: リクエスト状況のセットがビュー登録と一致する時は「最も特殊な」ものが呼ばれます。

例外ビュー設定を行う場合、正常に使用できない唯一のビュー述語は``name`` です。例外ビューを検索するために使用される名前は常に空の文字列です。例外ビューとして登録された名前を持つビューは無視されます。

注釈

ほとんどの場合、pyramid.config.Configurator.add_exception_view() を使用して exception view を登録する必要があります。 しかしながら、Exception (すなわち、config.add_view(context=Exception))を継承するコンテキストリソースタイプに対して「通常の」(すなわち例外ではない)ビューの登録が可能である。 ビュー構成が処理されると、2つのビューが登録されます。 1つは「通常の」ビュー、もう1つは exception view です。これは、通常のビューのコンテキストとして例外を使用できることを意味します。

これら2つのビューをラップするビューデリバーは、異なる動作をする可能性があります。 詳細については、 例外ビューとビューデリバー を参照してください。

例外ビューは任意のビュー登録メカニズムで構成できます: @view_config デコレータまたは命令的な add_view スタイル。

注釈

Pyramid の exception view 処理ロジックは pyramid.tweens.excview_tween_factory() という tween ファクトリ関数として実装されます。 Pyramid 例外ビューの処理が期待されて、 pyramid.tweens 設定で tween ファクトリが指定されている場合は、 pyramid.tweens 設定リストに pyramid.tweens.excview_tween_factory() 関数を明示的に追加しなければなりません。関数が存在しなければ、 Pyramid は例外ビューの処理を行ないません。

HTTP リダイレクトを行うためにcallableビューを使用する(Using a View Callable to do an HTTP Redirect)

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と文字集合の問題)Handling Form Submissions in View Callables (Unicode and Character Set Issues)

ほとんどのウェブアプリケーションは、ウェブブラウザおよび様々な他のクライアントからフォーム送信を受け取る必要があります。 Pyramid では、フォーム送信を扱うロジックは常に view の一部です。WebOb APIを使用してフォーム送信データを処理する方法の一般的な概要については、 (機械翻訳) 要求オブジェクトと応答オブジェクト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 を参照)"

注釈

Many people find the difference between Unicode and UTF-8 confusing. Unicode is a standard for representing text that supports most of the world's writing systems. However, there are many ways that Unicode data can be encoded into bytes for transit and storage. UTF-8 is a specific encoding for Unicode that is backwards-compatible with ASCII. This makes UTF-8 very convenient for encoding data where a large subset of that data is ASCII characters, which is largely true on the web. UTF-8 is also the standard character encoding for URLs.

例として、次のようなフォームページがブラウザクライアントに表示されて、その 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 トレーラーを加えます。独自のレスポンスオブジェクトを使用していれば、これを自分自身で確実に行う必要があるでしょう。

注釈

Only the values of request params obtained via request.params, request.GET or request.POST are decoded to Unicode objects implicitly in the Pyramid default configuration. The keys are still (byte) strings.

callableビューの引数/呼び出し規約を変更するAlternate View Callable Argument/Calling Conventions

通常、callableビューは単一の引数 request のみを受け取るように定義されています。しかし、その代わりにビュー callable はクラス、関数あるいは 2 つ の位置引数を受け取る何らかの callableとして定義されることも可能です: 1つ目の引数として context リソース、 2 つ目の引数として request です。

このスタイルで定義されたビュー関数に渡される contextrequest の各引数は、以下のように定義することができます:

コンテキスト
traversal ツリーあるいは URL dispatch によって見つかった resource オブジェクト。
リクエスト
現在のWSGIリクエストを表わす Pyramid リクエストオブジェクト。

次のタイプがこのスタイルのcallableビューとして動作します:

  1. 2つの引数 context, request を受け取る関数。例えば:

    1
    2
    3
    4
    from pyramid.response import Response
    
    def view(context, request):
        return Response('OK')
    
  2. Classes that have an __init__ method that accepts context, request, and a __call__ method which accepts no arguments, e.g.:

    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')
    
  3. 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 経由によってコンテキストにアクセスできます。

設定変数をビューへ渡す(Passing Configuration Variables to a View)

設定(.ini)ファイルからビューに変数を渡すことに関する情報は 展開設定 を参照してください。

Pylons 1.0 スタイルの "コントローラ" ディスパッチ(Pylons-1.0-Style "Controller" Dispatch)

pyramid_handlers という名のパッケージ (PyPI から利用可能) は Pylons スタイルの「コントローラ」の類似品を提供します。 Pylons スタイルの「コントローラ」の類似品を提供します。より多くの自動化を提供する特別な種類のビュークラスです。