【django】ログイン認証機能を組み込む方法(ログイン・ログアウト)

時計 2021.03.30 / 時計

【django】ログイン認証機能を組み込む方法(ログイン・ログアウト)

本記事ではPythonのWebフレームワークであるdjangoを使用して、ログイン認証機能を追加する方法について解説していきます。

Webアプリケーションを作成する上でログイン認証機能は必要不可欠な機能の一つです。

djangoには初めからログイン認証機能が提供されています。
本記事で紹介する方法を使うことで、簡単にログイン認証がご自身のWebアプリケーションに追加できるので、ぜひチャレンジしてみてください。

本記事で使用している各バージョンを次に示します。

Python 3.7.6

Django 3.1.6

mysqlclient 2.0.3

Webアプリケーションの準備

以下記事で作成されるプロジェクトoffice、アプリケーションfiveに対して認証機能を追加していきます。

以下に使用するWebアプリケーションのディレクトリ構成やソースコードを記します。

ディレクトリ構成

python
├── five
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── static
│   │   └── five
│   │        └── common.css
│   ├── templates
│   │   └── five
│   │        ├── base.html
│   │        └── index.html
│   ├── tests.py
│   └── views.py
├── manage.py
├── office
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── myvenv
  └── ...

ソースコード

base.html

{% load static %}
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE-edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0">
    <title>OFFICE54</title>
    <link rel="stylesheet" href="{% static 'five/common.css' %}">
    <script src="https://kit.fontawesome.com/d86c726e71.js" crossorigin="anonymous"></script>
</head>
<body>
    <header>
        <div>
            <p>OFFICE</p>
        </div>
        <div>
            <p><a href="#">ログイン</a></p>
        </div>
    </header>

    <div id="wrapper">
      <nav id="nav-left">
        <div id="nav">
          <ul id="nav-ul">
            <li class="nav-li"><a href="{% url 'index' %}" class="nav-li-a"><i class="fa fa-tachometer" style="margin-right:15px"></i>Dashboard</a></li>
            <li class="nav-li"><a href="#" class="nav-li-a"><i class="fas fa-list" style="margin-right:15px"></i>App1</a></li>
          </ul>
        </div>
      </nav>
      <main id="main">
          {% block content %}
          {% endblock %}
      </main>
    </div>
</body>
</html>

index.html

{% extends "five/base.html" %}
{% block content %}
<p>test</p>
{% endblock %}

urls.py:プロジェクト

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('five.urls')),
]

urls.py:アプリケーション

from django.urls import path
from . import views
urlpatterns = [
    path('', views.index, name='index'),
]

views.py

from django.shortcuts import render

def index(request):
    return render(request, 'five/index.html', {})

common.css

html *{
  margin: 0px;
  padding: 0px;
  box-sizing: border-box;
}
:root{
  font-family: "Arial","Hiragino Sans",YuGothic,"Yu Gothic","メイリオ",Meiryo;
  font-size: 17px;
  line-height: 1em;
}
p{
  letter-spacing: 0.05em;
  margin-top: 0.5em;
  margin-bottom: 0.5em;
  font-size: 1em;
  line-height: 1.5em;
}
header{
    height: 50px;
    box-shadow: 0px 0px 5px 0px hsla(0, 0%, 7%, 0.3);
    padding:0 20px 0;
}
header p{
    margin:0;
    font-size:30px;
    line-height:50px;
}
#wrapper{
    position:relative;
    height:100vh;
    padding-bottom:0px;
    display:flex;"
}
#nav-left{
     overflow: visible;
     height: 100%;
     width:230px;
     padding: 0;
     display: flex;
     background-color: #333;
     box-sizing: border-box;
     position: relative;
}
#nav{
    position: relative;
    top: 0px;
    left: 0px;
    margin-right: 0px;
    overflow: hidden;
    width: auto;
    height: auto;
    box-sizing: border-box;
    font-size: 12px;
}
#nav-ul{
    list-style:none;
    margin:0;
    padding:0;
}
.nav-li{
    height: 40px;
    width: 230px;
    color: white;
}
.nav-li-a{
    display: flex;
    align-items: center;
    line-height: 40px;
    padding-left: 15px;
    font-size: 15px;
    color:white;
}
#main{
    padding-left: 10px;
}

作成する認証機能を追加したWebアプリ

上記のソースコードに対してプログラムを記入していき、以下の画面遷移をする認証機能を追加したWebアプリケーションをこれから作成していきます。

  1. 未ログイン状態
  2. djangoによるwebアプリケーション:ログイン認証前
  3. ログインを押下して、ログインページが表示
  4. djangoによるwebアプリケーション:ログイン認証ページ
  5. 認証情報を入力・ログインして、ログイン後ページが表示
  6. djangoによるwebアプリケーション:ログイン認証後

ログイン後はheaderの表記が変わっているだけでなく、画面左のリストも増えています。

このように認証機能を使用することで、未ログインユーザーとログイン済みユーザーで表示する項目を制限することができます。

djangoの認証機能

django.contrib.auth

djangoに初めから組み込まれている認証機能はdjango.contrib.authから提供されます。

わかりやすく言うと、
django.contrib.authに保存されている、認証機能が記載されているビュー(view.py)やURLconf(urls.py)を使って、簡単に認証機能を実装できるということです。

これを利用することで、Webアプリケーションですぐに認証機能を使用することができます。

django-admin startprojectで作成されるプロジェクト内にはsettings.pyがあります。
その中のINSTALLED_APPSには、認証機能を組み込むためにdjango.contrib.authが記載されています。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'five.apps.FiveConfig',    # アプリケーションを追加している
]

また本記事で使用するモデルはデフォルトで作成されるdjango.contrib.auth内のUserモデルです。

django.contrib.auth.models.User

すでにUserモデルには「python manage.py createsuperuser」で作成したスーパーユーザーが保存されていると思いますので、本記事ではそのユーザーで認証を行います。

django.contrib.auth.urls

認証機能のURLパターンはdjango.contrib.auth.urlsに用意されています。
仮想環境venvを使用している場合は、次のパスに保存されています。

venv\Lib\site-packages\django\contrib\auth\urls.py

django.contrib.auth.urlsで提供されるURLconfは次のように、様々な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']

path('accounts/', include('django.contrib.auth.urls'))

プロジェクトoffice内のurls.pyに次の一文を追加することで、django.contrib.auth.urlsのURLパターンが有効になります。

path('accounts/', include('django.contrib.auth.urls')),

つまり、テンプレートを作成するだけで、用意されている認証機能を使えるようになるということです。

これによりurls.pyは次のようになります。

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('django.contrib.auth.urls')),    # 追加
    path('', include('five.urls')),
]

ログイン画面のテンプレートの作成

registrationフォルダを作成

templatesフォルダの直下にregistrationフォルダを作成します。

registrationフォルダは、この後作成するログイン画面のテンプレートを入れるのに使用します。

認証機能で使用するテンプレート名

registrationフォルダや、これから作成するlogin.html、logged_out.htmlのフォルダ名・テンプレート名は、django.contrib.auth内のviews.pyで決められています。
そのため別の名前を付けないように気を付けてください。

機能 テンプレート名
ログイン registration/login.html
ログアウト registration/logged_out.html
パスワード変更 registration/password_change_form.html
パスワードリセット registration/password_reset_form.html
パスワードリセット完了 registration/password_reset_done.html

login.htmlの作成

templates/registrationフォルダ内にlogin.htmlを作成します。
login.htmlはログイン画面を表示するテンプレートです。

{% extends "five/base.html" %}
{% block content %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
{% endblock %}

index.htmlの編集

ログインページへのリンク

aタグ内のリンクを{% url 'login' %}として、ログインページに遷移できるようにします。

<p><a href="{% url 'login' %}">ログイン</a></p>

ログインしているかの判別

ユーザーがログインしているかを判別するためには、user.is_authenticatedとif文を組み合わせて使用します。

{% if user.is_authenticated %}
    ログインしている場合に表示される
{% else %}
    未ログインの場合に表示される
{% endif %}

これを使用することで、ログイン済みユーザーと未ログインユーザーで表示する項目を分けることが可能となります。

この機能を使ってbase.htmlを次のように変更・追加します。

{% if user.is_authenticated %}
<p>こんにちは {{ user.username }}    <a href="{% url 'logout'%}">ログアウト</a></p>
{% else %}
<p><a href="{% url 'login' %}">ログイン</a></p>
{% endif %}

上記ではヘッダー部分に表示・非表示の項目を追加しています。

<ul id="nav-ul">
  <li class="nav-li"><a href="{% url 'index' %}" class="nav-li-a"><i class="fa fa-tachometer" style="margin-right:15px"></i>Dashboard</a></li>
  <li class="nav-li"><a href="#" class="nav-li-a"><i class="fas fa-list" style="margin-right:15px"></i>App1</a></li>
  {% if user.is_authenticated %}
  <li class="nav-li"><a href="#" class="nav-li-a"><i class="fas fa-server" style="margin-right:15px"></i>User Settings</a></li>
  {% endif %}
</ul>

上記では左メニューに、ログインユーザーのみに表示する項目を追加しています。

settings.pyの編集

settings.pyでログイン後の遷移先URL、ログアウト後の遷移先URLなどを設定します。

LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'

設定 意味
LOGIN_URL ログインしていない場合の遷移先URL
LOGIN_REDIRECT_URL ログイン後の遷移先URL
LOGOUT_REDIRECT_URL ログアウト後の遷移先URL

ソースコード:ログイン認証機能を追加版

以下にここまでで紹介したログイン認証機能を追加したWebアプリケーションのソースコードを記します。

実際にログイン機能が動作しているかご自身の端末で確かめてみてください。

base.html

{% load static %}
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE-edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0">
    <title>OFFICE54</title>
    <link rel="stylesheet" href="{% static 'five/common.css' %}">
    <script src="https://kit.fontawesome.com/d86c726e71.js" crossorigin="anonymous"></script>
</head>
<body>
    <header>
        <div>
            <p>OFFICE</p>
        </div>
        <div>
            {% if user.is_authenticated %}
            <p>こんにちは {{ user.username }}    <a href="{% url 'logout'%}">ログアウト</a></p>
            {% else %}
            <p><a href="{% url 'login' %}">ログイン</a></p>
            {% endif %}
        </div>
    </header>

    <div id="wrapper">
      <nav id="nav-left">
        <div id="nav">
          <ul id="nav-ul">
            <li class="nav-li"><a href="{% url 'index' %}" class="nav-li-a"><i class="fa fa-tachometer" style="margin-right:15px"></i>Dashboard</a></li>
            <li class="nav-li"><a href="#" class="nav-li-a"><i class="fas fa-list" style="margin-right:15px"></i>App1</a></li>
            {% if user.is_authenticated %}
            <li class="nav-li"><a href="#" class="nav-li-a"><i class="fas fa-server" style="margin-right:15px"></i>User Settings</a></li>
            {% endif %}
          </ul>
        </div>
      </nav>
      <main id="main">
          {% block content %}
          {% endblock %}
      </main>
    </div>
</body>
</html>

urls.py:プロジェクト

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('django.contrib.auth.urls')),
    path('', include('five.urls')),
]

common.css

cssには以下を追加しました。

h2{
    margin:20px 0;
}
header{
    display:flex;
    justify-content: space-between;
    height: 50px;
    box-shadow: 0px 0px 5px 0px hsla(0, 0%, 7%, 0.3);
    padding:0 20px 0;
}

まとめ

本記事「【django】ログイン認証機能を組み込む方法(ログイン・ログアウト)」はいかがでしたか。

djangoに備わっているログイン認証機能を使えば、一から作る必要がなくなり、簡単にログイン機能を実装できます。
ぜひご自身のWebアプリケーションに実装してみてください。