メッセージフレームワーク

revision-up-to:17812 (1.4)

Web アプリケーションでは一般的に、フォーム処理などのユーザによる入力の後に、一 度だけのメッセージ表示(フラッシュメッセージとも呼ばれる)を行いたいことが有りま す。

このために、Django はクッキー及びセッションベースのメッセージ処理を、匿名ユーザ と認証済みユーザの両方に対してサポートしています。このメッセージ機能 (messages) は、その後の(通常は次の)リクエストで表示するための、一時的なメッセージの保存と 取得を可能にします。全てのメッセージは特定の メッセージレベル (level) と共 にタグ付けされます(例えば、infowarning または error など)。

メッセージ機能を有効にする

メッセージ機能は ミドルウェア クラスと コンテキ ストプロセッサ を介して実装されています。

django-admin.py startproject によって作られるデフォルトの settings.py には、メッセージ機能を有効にするための以下の全ての設定が既に含まれています。

もし、メッセージ機能を使いたくない場合は、 INSTALLED_APPS から 'django.contrib.messages' を、 MIDDLEWARE_CLASSES から MessageMiddleware の行を、そして TEMPLATE_CONTEXT_PROCESSORS から messages を削除して下さい。

メッセージ処理の設定をする

ストレージバックエンド

このメッセージフレームワークでは、一時的にデータを保存するバックエンドとして、 さまざまなものを使うことができます。

Django は、3 つの組み込みストレージクラスを提供しています。

class django.contrib.messages.storage.session.SessionStorage

このクラスは、リクエストのセッション内に全てのメッセージを保存します。 つまり、Django の contrib.sessions アプリケーションが必要になります。

class django.contrib.messages.storage.cookie.CookieStorage

このクラスは、メッセージデータをクッキー内(secret hash 認証による改ざん対策 がされている)に保存することで、リクエスト間をまたがった通知を行います。古い メッセージは、クッキーのデータサイズが 2048 バイトを超えた際に削除されます。

class django.contrib.messages.storage.fallback.FallbackStorage

このクラスは、最初に CookieStorage を使い、メッセージがひとつのクッキー 内に収まらない場合は SessionStorage を使います。これもまた Django の contrib.sessions アプリケーションを必要とします。

この仕様によって、可能な限りセッションへの記録を行いません。これは一般的な ケースにおいて、最も良いパフォーマンスを提供するでしょう。

FallbackStorage がデフォルト のストレージクラスです。もしこれがあなたの要件に適していないなら、他のストレー ジクラスへのインポートパスを以下の例の様に MESSAGE_STORAGE へ設定し て下さい:

MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'

あなた独自のストレージクラスを書くには、django.contrib.messages.storage.base にある BaseStorage クラスのサブクラスを定義し、_get_store メソ ッドを実装して下さい。

メッセージレベル

メッセージフレームワークは、Python の logging モジュールに似た設定可能なレベル の仕組みを基本としています。メッセージレベル (message levels) は、タイプによっ てグループ化することで、メッセージがフィルタリングされ、各ビューやテンプレート で違う表示になるようにします。

django.contrib.messages から直接読み込まれる組み込みレベルは:

定数名 目的
DEBUG 開発用のメッセージ、本番環境では無視される(または削除される)
INFO ユーザーに対して情報を伝えるためのメッセージ
SUCCESS アクションが成功した、例) “あなたのプロフィールの更新が成功しました”
WARNING 失敗ではないが、その危険性がある
ERROR アクションが成功していないか、何かの失敗がある

MESSAGE_LEVEL の設定は、メッセージを記録するレベルの最小値 (minimum recorded level) を変更するために使われます(また、 `リクエスト別の設定`_ が可能 です)。試しにこれより低いレベルのメッセージを追加してみると、無視されることでし ょう。

メッセージタグ

メッセージタグ (message tags) とは、メッセージレベルを文字列によって表現したも のです。加えて、ビュー内で直接追加される拡張タグがあります(詳細は 拡張メッセージタグを追加する を参照)。複数のタグはひとつの文字列内に格納され 、スペースによって分割されています。一般的に、メッセージタグは、メッセージタイ プによるスタイルのカスタマイズを行う際のCSSクラス名として使われます。デフォルト では、各々のレベルには、定数名を小文字に変換した文字列のタグが付与されています。

レベル定数名 タグ文字列
DEBUG debug
INFO info
SUCCESS success
WARNING warning
ERROR error

メッセージレベルのデフォルトタグ(組み込みとカスタムタグのどちらでも)を変更するに は、 MESSAGE_TAGS へ変更したいレベルを含めた辞書を設定します。 その場合は、上書きしたいレベルだけを指定してタグを設定します。:

from django.contrib.messages import constants as messages
MESSAGE_TAGS = {
    messages.INFO: '',
    50: 'critical',
}

ビューとテンプレート内でメッセージを使う

add_message(request, level, message, extra_tags='', fail_silently=False)

メッセージを追加する

メッセージの追加:

from django.contrib import messages
messages.add_message(request, messages.INFO, 'Hello world.')

いくつかのショートカットメソッドは、一般に使われるタグ(通常はHTMLのクラス名になる )と共にメッセージ追加の標準的な手段を提供します:

messages.debug(request, '%s SQL statements were executed.' % count)
messages.info(request, 'Three credits remain in your account.')
messages.success(request, 'Profile details updated.')
messages.warning(request, 'Your account expires in three days.')
messages.error(request, 'Document deleted.')

メッセージを表示する

テンプレート内で、このような使い方をします:

{% if messages %}
<ul class="messages">
    {% for message in messages %}
    <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
    {% endfor %}
</ul>
{% endif %}

もし、あなたがコンテキストプロセッサを使っている場合、あなたのテンプレートは RequestContext を使ってレンダリングされないといけません。そうでないならば、 message をテンプレート内で使えるようにして下さい。

たとえ、メッセージが一つであったとしても、それでも messages をイテレートし なければなりません、なぜなら、そうしなければ、そのメッセージのストレージが次の リクエストまでに削除されないからです。

カスタムメッセージレベルを作成する

メッセージレベルは単なる整数に過ぎません、だから、あなたは独自のレベルの定数を 定義して、よりカスタムされたユーザのフィードバックを生成できます。例えば:

CRITICAL = 50

def my_view(request):
    messages.add_message(request, CRITICAL, 'A serious error occurred.')

カスタムメッセージレベルを作成した時、存在するレベルのオーバーロードをしないよ うに注意しないといけません。以下は組み込みレベルが使用している値です:

レベル定数名
DEBUG 10
INFO 20
SUCCESS 25
WARNING 30
ERROR 40

もしカスタムレベルに対してHTMLやCSS内で使うためのIDが欲しいなら、 MESSAGE_TAGS で設定をする必要があります。

Note

再利用可能なアプリケーションを作る場合は、組み込みのメッセージレベル のみを使い、カスタムレベルに頼らないことが推奨されています。

リクエスト別に記録するレベルの最小値を変更する

記録するレベルの最小値 (minimum recorded level) は、 set_level メソッドを使 うことでリクエスト別に設定をすることが出来ます:

from django.contrib import messages

# Change the messages level to ensure the debug message is added.
messages.set_level(request, messages.DEBUG)
messages.debug(request, 'Test message...')

# In another request, record only messages with a level of WARNING and higher
messages.set_level(request, messages.WARNING)
messages.success(request, 'Your profile was updated.') # ignored
messages.warning(request, 'Your account is about to expire.') # recorded

# Set the messages level back to default.
messages.set_level(request, None)

同様に、現在のレベルを get_level で取得することが出来ます:

from django.contrib import messages
current_level = messages.get_level(request)

記録するレベルの最小値についての情報は、先に メッセージレベル を参照して下さ い。

拡張メッセージタグを追加する

直接メッセージタグの操作をするには、各種追加用のメソッドにて任意で拡張メッセー ジタグ (extra tags) の文字列を設定することができます:

messages.add_message(request, messages.INFO, 'Over 9000!',
                     extra_tags='dragonball')
messages.error(request, 'Email box full', extra_tags='email')

拡張メッセージタグは、そのメッセージレベルのデフォルトタグの前に追加され、スペ ースで分割されます。

メッセージフレームワークが無効でもエラーを発生しない

再利用可能なアプリケーション(またはコード片)を書く際に、あなたにはメッセージ機 能が必要だがアプリケーションのユーザには必要でなかった場合、以下の例のように、 add_message とそれに類するメソッドへ fail_silently=True をキーワード引 数で追加すればエラーの発生を抑止することが出来ます:

messages.add_message(request, messages.SUCCESS, 'Profile details updated.',
                     fail_silently=True)
messages.info(request, 'Hello world.', fail_silently=True)

Note

fail_silently=True の設定は、メッセージフレームワークが無効の状態で add_message などのメソッドを使った時の MessageFailure エラーのみを隠 蔽し、その他のエラーは発生させます。他の原因で発生するエラーを隠蔽しません。

メッセージの有効期限

メッセージのデータは、ストレージのインスタンスをイテレートした時に、削除対象と してマークされます(そして、レスポンスが実行された際に削除されます)。

メッセージが削除されないようにするためには、イテレート後にストレージインスタン スへ False を設定します:

storage = messages.get_messages(request)
for message in storage:
    do_something_with(message)
storage.used = False

並列リクエスト時の挙動

クッキー(とセッション)を使用している対価として、 いかなるバックエンドを使って も、複数のリクエストが並列で実行された時には、それらのクッキーやセッションの動 きは不安定になります。例えば、もしクライアントがあるウィンドウ(またはタブ) でメッセージを生成するリクエストを行って、そして次に別ウィンドウで、その未処理 のメッセージを取得するリクエストを最初のウィンドウがリダイレクトする前に行ったら 、予想されるメッセージの表示場所は、最初のウィンドウではなく二番目のウィンドウ です。

短い間に、複数のリクエストが同じクライアントから送信されると、ほとんどの場合に おいて、メッセージがウィンドウに表示されることも作成されることも保証されません 。また、覚えておくこととして、この点は一般的なアプリケーションでは問題にならず 、そして HTML5 では、ウィンドウ/タブのそれぞれがコンテキストを持つようになるの で、 全く問題にならなくなるでしょう。

設定

少しの設定でメッセージの動きを操作出来ます:

  • MESSAGE_LEVEL
  • MESSAGE_STORAGE
  • MESSAGE_TAGS
  • SESSION_COOKIE_DOMAIN