Djangoメモ(21) : ユーザー認証を実装する〜ログアウト
A Complete Beginner's Guide to Djangoのチュートリアルを参考にログアウト機能を実装する。
ログアウトビュー
ドキュメントによるとDjangoではログイン、ログアウト、パスワード管理のビューは提供されている(サインアップは提供されていない)のでそれを利用する。ただし、テンプレートに関しては提供されていないので自分で実装する必要がある。
以下のようにURLConfを設定すると、
urlpatterns = [ path('accounts/', include('django.contrib.auth.urls')), ]
下記URLの全パターンが有効になる。
accounts/login/ [name='login'] accounts/logout/ [name='logout'] accounts/password_change/ [name='password_change'] accounts/password_change/done/ [name='password_change_done'] accounts/password_reset/ [name='password_reset'] accounts/password_reset/done/ [name='password_reset_done'] accounts/reset/<uidb64>/<token>/ [name='password_reset_confirm'] accounts/reset/done/ [name='password_reset_complete']
ただし、チュートリアルでは順番に実装していっているためログアウトビューのみを設定する。
myproject/urls.py
にlogout/
の行を追加。
from django.contrib import admin from django.conf import settings from django.urls import path, include from django.contrib.auth import views as auth_views from accounts import views as accounts_views from boards import views urlpatterns = [ path('', views.home, name='home'), path('signup/', accounts_views.signup, name='signup'), path('logout/', auth_views.LogoutView.as_view(), name='logout'), path('boards/<int:pk>/', views.board_topics, name='board_topics'), path('boards/<int:pk>/new/', views.new_topic, name='new_topic'), path('admin/', admin.site.urls), ]
個別に設定する場合はauth_views.LogoutView.as_view()
のように設定するが、これはクラスベースビューの書き方とのこと。
次にmyproject/settings.py
にログアウト後のリダイレクト先URLを設定する。
LOGOUT_REDIRECT_URL = 'home'
これで設定は完了で、logout/
(例:127.0.0.1:8000/logout/
)にアクセスするとログアウトし、home
ページにリダイレクトされる。
ログアウト後はCookieのsessionid
も消えていることが確認できる。
ログアウトメニュー追加
logout/
リンクをクリックできるようにログアウト用のドロップダウンメニューを追加する。
チュートリアルではjQuery, Popper.js, Bootstrap(BootstrapのDropdownsを使うためにはjQuery, Popper.jsが必要)のJavaScriptを利用しているのでそれぞれのサイトからダウンロードする。
ファイルのダウンロードリンク(右クリックで保存)
ファイルをダウンロードしたら以下のディレクトリ、ファイル構成になるように配置する。
├── static/ │ ├── css/ │ │ ├── accounts.css │ │ ├── app.css │ │ └── bootstrap.min.css │ ├── img/ │ │ └── vintage-leaves.png │ └── js/ │ ├── bootstrap.min.js │ ├── jquery-3.3.1.min.js │ └── popper.min.js └── templates/
JavaScriptを読み込むようにtemplates/base.html
の後半に<script>
タグを追加する。
{% load static %}<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>{% block title %}Django Boards{% endblock %}</title> <link href="https://fonts.googleapis.com/css?family=Pacifico" rel="stylesheet"> <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}"> <link rel="stylesheet" href="{% static 'css/app.css' %}"> {% block stylesheet %}{% endblock %} </head> <body> {% block body %} 省略 {% endblock body %} <script src="{% static 'js/jquery-3.3.1.min.js' %}"></script> <script src="{% static 'js/popper.min.js' %}"></script> <script src="{% static 'js/bootstrap.min.js' %}"></script> </body> </html>
次にドロップダウンメニューを表示するようにtemplates/base.html
の<nav>
内を以下のように変更する。
<nav class="navbar navbar-expand-sm navbar-dark bg-dark"> <div class="container"> <a class="navbar-brand" href="{% url 'home' %}">Django Boards</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#mainMenu" aria-controls="mainMenu" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="mainMenu"> <ul class="navbar-nav ml-auto"> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" href="#" id="userMenu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> {{ user.username }} </a> <div class="dropdown-menu dropdown-menu-right" aria-labelledby="userMenu"> <a class="dropdown-item" href="#">My account</a> <a class="dropdown-item" href="#">Change password</a> <div class="dropdown-divider"></div> <a class="dropdown-item" href="{% url 'logout' %}">Log out</a> </div> </li> </ul> </div> </div> </nav>
ドロップダウンメニューが表示されるようになるのでLog outをクリックしてみる。
ログアウトは成功し、ユーザー名の部分が表示されなくなる。
これでは表示がいまいちなので、ログアウト時には別のボタンを表示するようにtemplates/base.html
の<nav>
内を改良する。
<nav class="navbar navbar-expand-sm navbar-dark bg-dark"> <div class="container"> <a class="navbar-brand" href="{% url 'home' %}">Django Boards</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#mainMenu" aria-controls="mainMenu" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="mainMenu"> {% if user.is_authenticated %} <ul class="navbar-nav ml-auto"> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" href="#" id="userMenu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> {{ user.username }} </a> <div class="dropdown-menu dropdown-menu-right" aria-labelledby="userMenu"> <a class="dropdown-item" href="#">My account</a> <a class="dropdown-item" href="#">Change password</a> <div class="dropdown-divider"></div> <a class="dropdown-item" href="{% url 'logout' %}">Log out</a> </div> </li> </ul> {% else %} <form class="form-inline ml-auto"> <a href="#" class="btn btn-outline-secondary">Log in</a> <a href="{% url 'signup' %}" class="btn btn-primary ml-2">Sign up</a> </form> {% endif %} </div> </div> </nav>
{% if user.is_authenticated %}
でログイン中であるかを判定し、ログイン中の場合はドロップダウンメニューを表示し、ログアウト時はログイン、サインアップボタンを表示するようにしている。
まとめ
- Djangoではログイン、ログアウト、パスワード管理のビューが提供されている
include('django.contrib.auth.urls')
で認証関連のビューを全部読み込めるauth_views.LogoutView.as_view()
のように個別に設定できるLOGOUT_REDIRECT_URL = 'home'
でログアウト後のリダイレクト先を指定- BootstrapのDropdownsでログアウトのドロップダウンメニューを作成
- テンプレートでは
{% if user.is_authenticated %}
でログイン状態を判定