【Django】フラッシュメッセージを実装する|簡単な掲示板アプリの作成
Djangoの標準機能「messagesフレームワーク」を用いて、ユーザーの操作結果を知らせるフラッシュメッセージの実装方法を解説します。投稿成功やログイン失敗などの通知を画面に表示し、jQueryを使って数秒後に自動でフェードアウトさせる方法まで、初心者にも分かりやすく学べます。
開発環境
- OS: Windows10
- Visual Studio Code: 1.73.0
- Python: 3.10.11
- Django: 5.0.3
サンプルコード
/app/views.py
/app/views.py1 from django.conf import settings 2 from django.template.loader import render_to_string 3 from django.core.paginator import Paginator 4+from django.contrib import messages 5 6 def user_owns_board(view_func): 7 @wraps(view_func) 8 if form.is_valid(): 9 form.instance.user = request.user 10 form.save() 11+ messages.success(request, '投稿が成功しました!') 12 return redirect('index') 13+ else: 14+ messages.error(request, '入力内容にエラーがあります。') 15 else: 16 form = BoardForm() 17 return render(request, 'new.html', {'form': form}) 18 class CustomLoginView(LoginView): 19 template_name = 'registration/login.html' 20 21+ def form_valid(self, form): 22+ # ログインに成功した場合の処理 23+ messages.success(self.request, 'ログインに成功しました。') 24+ return super().form_valid(form) 25+ 26+ def form_invalid(self, form): 27+ # ログインに失敗した場合の処理 28+ messages.error(self.request, 'ログインに失敗しました。ユーザー名とパスワードを確認してください。') 29+ return super().form_invalid(form) 30+ 31 # ログアウト 32 def logout_view(request): 33 logout(request) 34+ messages.success(request, 'ログアウトに成功しました。') 35 return redirect('index') 36 37 # サインアップページのビュー 38 form = SignUpForm(request.POST) 39 if form.is_valid(): 40 form.save() 41+ messages.success(request, 'サインアップに成功しました。') 42 return redirect('login') 43+ else: 44+ messages.error(request, '入力内容にエラーがあります。') 45 else: 46 form = SignUpForm() 47 return render(request, 'registration/signup.html', {'form': form}) 48
/config/settings.py
/config/settings.py1 "django.middleware.clickjacking.XFrameOptionsMiddleware", 2 ] 3 4+MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage' 5+ 6 ROOT_URLCONF = "config.urls" 7 8 TEMPLATES = [ 9
/config/urls.py
/config/urls.py1 from django.urls import path, include 2 from django.contrib.auth import views as auth_views 3 from app import views 4+from app.views import CustomLoginView 5 6 urlpatterns = [ 7 path("admin/", admin.site.urls), 8 path('', include('app.urls')), 9- path('accounts/login/', auth_views.LoginView.as_view(), name='login'), 10+ path('accounts/login/', CustomLoginView.as_view(), name='login'), 11 path('accounts/logout/', views.logout_view, name='logout'), 12 path('accounts/signup/', views.signup, name='signup'), 13 path('accounts/profile/', views.profile, name='profile'), 14
/static/js/common.js
/static/js/common.js1+// ページロード時にフラッシュメッセージをフェードアウトする 2+$(document).ready(function(){ 3+ $(".alert").delay(3000).fadeOut("slow"); 4+}); 5
/templates/base.html
/templates/base.html1 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css"> 2 <!-- CSSファイルを読み込む --> 3 <link rel="stylesheet" type="text/css" href="{% static 'css/styles.css' %}"> 4+ <!-- jQueryのCDNを読み込む --> 5+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> 6+ <!-- BootstrapのCDNを読み込む --> 7+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script> 8+ <!-- 静的ファイルとして保存されたJavaScriptを読み込む --> 9+ <script src="{% static 'js/common.js' %}"></script> 10 </head> 11 <body> 12 <!-- ヘッダーの内容 --> 13 </div> 14 </header> 15 16+ <!-- フラッシュメッセージ --> 17+ {% if messages %} 18+ <div class="text-center"> 19+ {% for message in messages %} 20+ {% if message.tags == 'success' %} 21+ <div class="alert alert-success alert-dismissible fade show" role="alert"> 22+ {{ message }} 23+ <button type="button" class="btn-close" data-dismiss="alert" aria-label="Close"></button> 24+ </div> 25+ {% elif message.tags == 'error' %} 26+ <div class="alert alert-danger alert-dismissible fade show" role="alert"> 27+ {{ message }} 28+ <button type="button" class="btn-close" data-dismiss="alert" aria-label="Close"></button> 29+ </div> 30+ {% endif %} 31+ {% endfor %} 32+ </div> 33+ {% endif %} 34+ 35 <!-- 各ページの内容 --> 36 <main> 37 <div class="container"> 38
コード解説
変更点: メッセージを保存する方法の設定
/config/settings.py1 "django.middleware.clickjacking.XFrameOptionsMiddleware", 2 ] 3 4+MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage' 5+ 6 ROOT_URLCONF = "config.urls" 7 8 TEMPLATES = [
settings.pyファイルに MESSAGE_STORAGE という設定を追加しています。これは、Djangoのmessagesフレームワークが生成したメッセージをどこに保存するかを指定するためのものです。'django.contrib.messages.storage.session.SessionStorage' を指定することで、メッセージがユーザーのセッション情報の中に一時的に保存されます。これにより、リクエストをまたいで、例えば投稿処理後のリダイレクト先ページで「投稿が成功しました!」といったメッセージを表示できるようになります。
変更点: ビューでmessagesフレームワークをインポート
/app/views.py1 from django.conf import settings 2 from django.template.loader import render_to_string 3 from django.core.paginator import Paginator 4+from django.contrib import messages
views.pyファイルで、from django.contrib import messages という行を追加しました。これは、Djangoに標準で備わっているmessagesフレームワークの機能(例: messages.success())をビューの中で使えるようにするために必要なインポート文です。
変更点: 掲示板への投稿処理にメッセージを追加
/app/views.py1 if form.is_valid(): 2 form.instance.user = request.user 3 form.save() 4+ messages.success(request, '投稿が成功しました!') 5 return redirect('index') 6+ else: 7+ messages.error(request, '入力内容にエラーがあります。')
新規投稿を行うビュー new_board の処理を修正しています。
フォームへの入力が正しく、投稿が成功した場合には messages.success(request, '投稿が成功しました!') を実行します。これは、「成功」レベルのメッセージを登録する命令です。
一方、フォームの入力に誤りがあった場合には messages.error(request, '入力内容にエラーがあります。') を実行し、「エラー」レベルのメッセージを登録しています。
request を第一引数に渡すことで、どのユーザーのリクエストに対するメッセージかをDjangoが判断できるようになります。
変更点: ログイン処理にメッセージを追加
/app/views.py1 class CustomLoginView(LoginView): 2 template_name = 'registration/login.html' 3 4+ def form_valid(self, form): 5+ # ログインに成功した場合の処理 6+ messages.success(self.request, 'ログインに成功しました。') 7+ return super().form_valid(form) 8+ 9+ def form_invalid(self, form): 10+ # ログインに失敗した場合の処理 11+ messages.error(self.request, 'ログインに失敗しました。ユーザー名とパスワードを確認してください。') 12+ return super().form_invalid(form)
Djangoの標準ログインビュー LoginView を継承した CustomLoginView を作成し、処理をカスタマイズしています。
form_valid メソッドはログインが成功したときに呼び出されます。ここで messages.success() を使い、成功メッセージを登録しています。
form_invalid メソッドはログインが失敗したときに呼び出されます。ここでは messages.error() を使い、失敗メッセージを登録しています。
super().form_valid(form) は、親クラス(元のLoginView)の本来の処理を呼び出すための記述です。
変更点: ログアウト処理にメッセージを追加
/app/views.py1 # ログアウト 2 def logout_view(request): 3 logout(request) 4+ messages.success(request, 'ログアウトに成功しました。') 5 return redirect('index')
ユーザーがログアウトする際のビュー logout_view に、messages.success(request, 'ログアウトに成功しました。') という行を追加しました。これにより、ログアウトが正常に完了したことをユーザーに知らせるメッセージが表示されるようになります。
変更点: サインアップ(ユーザー登録)処理にメッセージを追加
/app/views.py1 form = SignUpForm(request.POST) 2 if form.is_valid(): 3 form.save() 4+ messages.success(request, 'サインアップに成功しました。') 5 return redirect('login') 6+ else: 7+ messages.error(request, '入力内容にエラーがあります。')
サインアップ(新規ユーザー登録)のビューにメッセージ機能を追加しました。
フォームの入力内容が正しく、ユーザー登録が成功した場合は messages.success() で成功メッセージを登録します。
入力内容にエラーがあった場合は messages.error() でエラーメッセージを登録し、ユーザーに問題を知らせます。
変更点: カスタマイズしたログインビューを使うようにURLを変更
/config/urls.py1 from django.urls import path, include 2 from django.contrib.auth import views as auth_views 3 from app import views 4+from app.views import CustomLoginView 5 6 urlpatterns = [ 7 path("admin/", admin.site.urls), 8 path('', include('app.urls')), 9- path('accounts/login/', auth_views.LoginView.as_view(), name='login'), 10+ path('accounts/login/', CustomLoginView.as_view(), name='login'), 11 path('accounts/logout/', views.logout_view, name='logout'), 12 path('accounts/signup/', views.signup, name='signup'),
urls.py を編集し、ログインページのURL (/accounts/login/) が呼び出された際に、Django標準の LoginView ではなく、先ほどメッセージ機能を追加した CustomLoginView を使うように設定を変更しています。これにより、ログイン成功・失敗時にメッセージが表示されるようになります。
変更点: JavaScriptライブラリと自作JSファイルの読み込み
/templates/base.html1 <link rel="stylesheet" type="text/css" href="{% static 'css/styles.css' %}"> 2+ <!-- jQueryのCDNを読み込む --> 3+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> 4+ <!-- BootstrapのCDNを読み込む --> 5+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script> 6+ <!-- 静的ファイルとして保存されたJavaScriptを読み込む --> 7+ <script src="{% static 'js/common.js' %}"></script> 8 </head>
すべてのページの基礎となる base.html に、JavaScriptを動作させるためのコードを追加しました。
- jQuery: JavaScriptをより簡単に書くためのライブラリです。CDNという形式でインターネット上から直接読み込んでいます。
- Bootstrap: Webサイトのデザインを整えるBootstrapのJavaScript部分です。メッセージを閉じるボタンなどの機能に必要です。
- common.js: 私たちが作成したJavaScriptファイルです。
{% static 'js/common.js' %}という書き方で、Djangoが管理する静的ファイル(static)の中からこのファイルを読み込んでいます。
変更点: フラッシュメッセージを表示するためのHTMLを追加
/templates/base.html1 </header> 2 3+ <!-- フラッシュメッセージ --> 4+ {% if messages %} 5+ <div class="text-center"> 6+ {% for message in messages %} 7+ {% if message.tags == 'success' %} 8+ <div class="alert alert-success alert-dismissible fade show" role="alert"> 9+ {{ message }} 10+ <button type="button" class="btn-close" data-dismiss="alert" aria-label="Close"></button> 11+ </div> 12+ {% elif message.tags == 'error' %} 13+ <div class="alert alert-danger alert-dismissible fade show" role="alert"> 14+ {{ message }} 15+ <button type="button" class="btn-close" data-dismiss="alert" aria-label="Close"></button> 16+ </div> 17+ {% endif %} 18+ {% endfor %} 19+ </div> 20+ {% endif %} 21+ 22 <!-- 各ページの内容 --> 23 <main>
base.html に、ビューで登録されたフラッシュメッセージを実際に画面に表示するためのHTMLコードを追加しました。
{% if messages %}: Djangoのテンプレートタグです。表示すべきメッセージが存在する場合にのみ、内側のコードを実行します。{% for message in messages %}: 登録されているメッセージを1つずつ取り出して処理を繰り返します。{{ message }}: ビューで設定したメッセージの文字列(例: '投稿が成功しました!')がここに表示されます。{% if message.tags == 'success' %}: メッセージのレベル(successやerrorなど)を判定しています。これにより、成功メッセージは緑色 (alert-success)、エラーメッセージは赤色 (alert-danger) のように、BootstrapのCSSクラスを使って見た目を変えることができます。
変更点: メッセージを自動で消すJavaScriptコードの追加
/static/js/common.js1+// ページロード時にフラッシュメッセージをフェードアウトする 2+$(document).ready(function(){ 3+ $(".alert").delay(3000).fadeOut("slow"); 4+});
新しく作成した common.js ファイルに、jQueryを使ったコードを記述しました。
$(document).ready(function(){ ... });: ページのHTMLがすべて読み込まれた後に、中の処理を実行するという意味です。$(".alert"):alertというCSSクラスが指定されたHTML要素(今回の場合、フラッシュメッセージ全体)を選択します。.delay(3000): 3000ミリ秒、つまり3秒間、次の処理を待機させます。.fadeOut("slow"): 選択した要素をゆっくりとフェードアウト(だんだん薄くして消す)させます。 このコードにより、表示されたフラッシュメッセージが3秒後に自動的に消えるようになります。
おわりに
今回はDjangoのmessagesフレームワークを使い、フラッシュメッセージの実装方法を学びました。views.pyにて投稿やログインといった処理の結果に応じ、messages.success()やmessages.error()を呼び出すだけで簡単にメッセージを登録できることを確認しました。base.htmlでこれらのメッセージを表示し、さらにjQueryで数秒後に自動で消えるアニメーションを加えることで、ユーザーに分かりやすいフィードバックを提供できるようになります。この一連の実装は、ユーザーにとって使いやすいWebアプリケーションを開発するための重要な機能です。