revision-up-to: | 17812 (1.4) |
---|
Web アプリケーションでは一般的に、フォーム処理などのユーザによる入力の後に、一 度だけのメッセージ表示(フラッシュメッセージとも呼ばれる)を行いたいことが有りま す。
このために、Django はクッキー及びセッションベースのメッセージ処理を、匿名ユーザ
と認証済みユーザの両方に対してサポートしています。このメッセージ機能 (messages)
は、その後の(通常は次の)リクエストで表示するための、一時的なメッセージの保存と
取得を可能にします。全てのメッセージは特定の メッセージレベル
(level) と共
にタグ付けされます(例えば、info
、warning
または error
など)。
メッセージ機能は ミドルウェア クラスと コンテキ ストプロセッサ を介して実装されています。
django-admin.py startproject
によって作られるデフォルトの settings.py
には、メッセージ機能を有効にするための以下の全ての設定が既に含まれています。
INSTALLED_APPS
へ 'django.contrib.messages'
を含めるMIDDLEWARE_CLASSES
へ
'django.contrib.sessions.middleware.SessionMiddleware'
と
'django.contrib.messages.middleware.MessageMiddleware'
を含める
デフォルトの ストレージバックエンド
(storage backends) は セッション機能 に依存し
ています。そのため、 SessionMiddleware
は MIDDLEWARE_CLASSES
内で MessageMiddleware
より前に置いて有効にする必要があります。
TEMPLATE_CONTEXT_PROCESSORS
へ
'django.contrib.messages.context_processors.messages'
を含めるもし、メッセージ機能を使いたくない場合は、 INSTALLED_APPS
から
'django.contrib.messages'
を、 MIDDLEWARE_CLASSES
から
MessageMiddleware
の行を、そして TEMPLATE_CONTEXT_PROCESSORS
から
messages
を削除して下さい。
このメッセージフレームワークでは、一時的にデータを保存するバックエンドとして、 さまざまなものを使うことができます。
Django は、3 つの組み込みストレージクラスを提供しています。
django.contrib.messages.storage.session.
SessionStorage
¶このクラスは、リクエストのセッション内に全てのメッセージを保存します。
つまり、Django の contrib.sessions
アプリケーションが必要になります。
このクラスは、メッセージデータをクッキー内(secret hash 認証による改ざん対策 がされている)に保存することで、リクエスト間をまたがった通知を行います。古い メッセージは、クッキーのデータサイズが 2048 バイトを超えた際に削除されます。
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 では、ウィンドウ/タブのそれぞれがコンテキストを持つようになるの で、 全く問題にならなくなるでしょう。
Oct 26, 2017