【Django】ログイン画面・認証機能の作成|PythonによるWebアプリ開発#11

こんにちは、DXCEL WAVEの運営者(@dxcelwave)です!

PythonによるDjangoフレームワークを用いて「ログイン画面の作成方法」を徹底解説します。またログイン有無によるアクセス権限を指定し「会員のみアクセス可能なホーム画面」の作成方法についても詳しく解説します。

目次

ログイン画面の作成全体イメージ

画面体系イメージ

Djangoフレームワークにより作成する画面と画面遷移イメージを上図に示します。

新規登録画面、ログイン画面、ホーム画面のうち、本記事では「ログイン画面」と「ログイン可否によって挙動が変わるホーム画面」を中心に徹底解説します。

本記事ご覧の際は、事前に下記のアカウント登録画面の作成方法の記事をご覧になられることを推奨します。新規登録画面のソースコードやDB管理設定についてはこちらの記事で言及しています。

画面イメージ

続いて、新規登録フォームからアカウント登録、ログイン、トップ画面へ遷移する画面イメージを上図に示します。ログイン画面ではユーザーIDとパスワードを入力し、ログインするケースを検討します。

システム挙動イメージ

ログイン画面のシステム挙動を解説します。ユーザーIDとパスワードを入力したのち、ログインボタンを押すと、アカウント情報の認証が行われます。アカウントが正しく登録されている場合、ホーム画面に遷移する仕様を検討します。

ログインなしでホーム画面に遷移すると、アクセス拒否される仕様とします。

ディレクトリ構成

最後にディレクトリ構成の確認です。下記のスクリプトが編集対象です。

  • 画面表示定義:views.py
  • 画面表示定義:urls.py
  • 画面デザイン:各種HTML&CSSファイル

ログイン画面作成プロセス

ログイン画面・ホーム画面のコーディングを行なっていきます。作業手順の全体像は上図に該当します。以下順を追って解説します。

ログイン画面(HTML)

まず、ログイン画面のフロント部分のコーディングを行います。サンプルとして以下のようなHTMLを準備しました。適時ご活用ください。

<!DOCTYPE html>
{% load static %}
<html lang="ja" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href='{% static "App_Folder_css/style.css" %}'/>

</head>
<body>
<h1>ログイン画面</h1>

<div class="reg">
  <form method="post" action="{% url 'Login' %}">
    {% csrf_token %}

    <table class="reg_form">
    <tr>
    <td><label for="userid">ユーザーID:</label></td>
    <td><input type="text" name="userid"></td>
    <td><label for="password">パスワード:</label></td>
    <td><input type="password" name="password"></td>
    </tr>
    </table>

    <input type="submit" class="btn" value="Login">
 </form>
</div>
   <p class="message">アカウントをお持ちですか?:
   <a href="{% url 'register' %}">アカウントを作成</a>
   </p>
</body>
</html>

ホーム画面(HTML)

続いて、ホーム画面のHTMLコーディングを行います。適時以下のコード例をご利用ください。

<!DOCTYPE html>
{% load static %}
<html lang="ja" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href='{% static "App_Folder_css/css/style.css" %}'/>

</head>
<body>
 <h1><font color="red">{{ UserID }}</font>さんようこそ!!</h1>

 <p> ログアウトは
 <a href="{% url 'Logout' %}">こちら</a>
 </p>
</body>
</html>

画面デザイン(CSS)

ログイン画面およびホーム画面におけるCSSデザイン例を下記に示します。

h1{
  text-align: center;
}

div.reg{
  background-color: #EEEEEE;
  margin-left: 15%;
  margin-right: 15%;
}

.message{
  text-align: right;
  margin-right:20%;
}

table.reg_form{
  width: 100%;
  border-spacing: 10px 30px;
  padding-left:20px;
}

.btn{
    color: #fff;
    background-color: #000033;
    font-size: 1.0em;
    padding: 10px 30px;
    margin-left:80%;
}

.btn:hover{
  color: #fff;
  background: #000099;
}

表示設定(1)(views.py)

新規登録画面、ログインフォーム、トップページの表示設定を行います。views.pyを開き、下記のように記載しましょう。

from django.shortcuts import render
from django.views.generic import TemplateView #テンプレートタグ
from .forms import AccountForm, AddAccountForm #ユーザーアカウントフォーム

# ログイン・ログアウト処理に利用
from django.contrib.auth import authenticate, login, logout
from django.http import HttpResponseRedirect, HttpResponse
from django.urls import reverse
from django.contrib.auth.decorators import login_required

#ログイン
def Login(request):
    # POST
    if request.method == 'POST':
        # フォーム入力のユーザーID・パスワード取得
        ID = request.POST.get('userid')
        Pass = request.POST.get('password')

        # Djangoの認証機能
        user = authenticate(username=ID, password=Pass)

        # ユーザー認証
        if user:
            #ユーザーアクティベート判定
            if user.is_active:
                # ログイン
                login(request,user)
                # ホームページ遷移
                return HttpResponseRedirect(reverse('home'))
            else:
                # アカウント利用不可
                return HttpResponse("アカウントが有効ではありません")
        # ユーザー認証失敗
        else:
            return HttpResponse("ログインIDまたはパスワードが間違っています")
    # GET
    else:
        return render(request, 'App_Folder_HTML/login.html')


#ログアウト
@login_required
def Logout(request):
    logout(request)
    # ログイン画面遷移
    return HttpResponseRedirect(reverse('Login'))


#ホーム
@login_required
def home(request):
    params = {"UserID":request.user,}
    return render(request, "App_Folder_HTML/home.html",context=params)


#新規登録
class  AccountRegistration(TemplateView):

    def __init__(self):
        self.params = {
        "AccountCreate":False,
        "account_form": AccountForm(),
        "add_account_form":AddAccountForm(),
        }

    #Get処理
    def get(self,request):
        self.params["account_form"] = AccountForm()
        self.params["add_account_form"] = AddAccountForm()
        self.params["AccountCreate"] = False
        return render(request,"App_Folder_HTML/register.html",context=self.params)

    #Post処理
    def post(self,request):
        self.params["account_form"] = AccountForm(data=request.POST)
        self.params["add_account_form"] = AddAccountForm(data=request.POST)

        #フォーム入力の有効検証
        if self.params["account_form"].is_valid() and self.params["add_account_form"].is_valid():
            # アカウント情報をDB保存
            account = self.params["account_form"].save()
            # パスワードをハッシュ化
            account.set_password(account.password)
            # ハッシュ化パスワード更新
            account.save()

            # 下記追加情報
            # 下記操作のため、コミットなし
            add_account = self.params["add_account_form"].save(commit=False)
            # AccountForm & AddAccountForm 1vs1 紐付け
            add_account.user = account

            # 画像アップロード有無検証
            if 'account_image' in request.FILES:
                add_account.account_image = request.FILES['account_image']

            # モデル保存
            add_account.save()

            # アカウント作成情報更新
            self.params["AccountCreate"] = True

        else:
            # フォームが有効でない場合
            print(self.params["account_form"].errors)

        return render(request,"App_Folder_HTML/register.html",context=self.params)

以下、上記スクリプトの意味を1つずつ解説していきます。

Login()関数

まず、ログイン実行(POST処理)の際、ユーザーIDとパスワードを取得します。ここでPOST処理時に取得する各値は、get(“HTMLファイル: inputタグのname属性”)として指定することで取得できます。

    if request.method == 'POST':
        # フォーム入力のユーザーID・パスワード取得
        ID = request.POST.get('userid')
        Pass = request.POST.get('password')

ログイン時のユーザー認証は下記のように定義しています。まず、user.is_activateと指定し、Bool値を返します。この値が真の場合、後述のログイン操作が実行されます。

            #ユーザーアクティベート判定(
            if user.is_active:
                # ログイン
                login(request,user)
                # ホームページ遷移
                return HttpResponseRedirect(reverse('home'))

Logout()関数

ログアウト関数は、原則ログイン時のみ有効化したい関数です。そのために下記のモジュールをインポートし、関数上部に@login_requiredと記載することで、ログイン時のみ有効な関数として動作させます。

from django.contrib.auth.decorators import login_required
#ログアウト
@login_required
def Logout(request):
    logout(request)
    # ログイン画面遷移
    return HttpResponseRedirect(reverse('Login'))

home関数(ホーム画面用)

ログイン中のステータスのみ遷移可能なホーム画面とするには、ログアウト同様、関数上部に@login_requiredと記載します。

@login_required
def home(request):
    params = {"UserID":request.user,}
    return render(request, "App_Folder_HTML/home.html",context=params)

これにてviews.pyでの画面表示設定は完了です!本記事ではアカウント新規登録画面の説明は割愛します。

表示設定(2)(urls.py)

新規登録画面、ログイン画面、ホーム画面のURLマッピングを行います。下記のように記載してみましょう。

プロジェクト管理フォルダ(Project_Folder)のurls.py

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

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

アプリケーション管理フォルダ(App_Folder)のurls.py

from django.urls import path
from . import views

urlpatterns = [
    path('',views.Login,name='Login'),
    path("logout",views.Logout,name="Logout"),
    path('register',views.AccountRegistration.as_view(), name='register'),
    path("home",views.home,name="home"),
]

動作確認!ログイン・ログアウト

これにてコーディングは全て完了です!最後に実際に画面を見ながら動作確認してみましょう。ターミナルを開き、以下入力し、ローカルサーバーへアクセスします。

python manage.py runserver
http://localhost:8000/

【参考】Djangoの解説記事一覧

最後までご覧いただきありがとうございました。当サイトではDjangoフレームワークを用いた解説記事を多数取り扱っております。次のように体系的に整理しておりますため学習にお役立て下さい。

Django学習に最適!

当サイトが運営するDjango記事一覧

【参考】Pythonでできること・お仕事探し

最後に

この記事が気に入ったら
フォローしてね!

本記事をシェア!
目次