【Django】ログインアカウント用新規登録フォームの作成|PythonによるWebアプリ開発#10

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

PythonによるDjangoフレームワークを用いて「ユーザーがログインするために必要な新規アカウント登録画面の作成方法」についてご紹介します。新規登録画面からアカウントを登録し、セキュリティ考慮上パスワードをハッシュ化し、アカウント情報をデータベースに登録されるまでを範囲とした主要なコーディングを全て公開します。

目次

【Django】ユーザー新規登録画面の作成全体イメージ

画面体系イメージ

Djangoフレームワークを用いて作成予定の画面と画面遷移イメージを上図に示します。新規登録画面、ログイン画面、ホーム画面のうち、本記事では「新規登録画面」に絞り、徹底解説していきます。

ログイン画面の作成について詳しく知りたい方は、本記事見出し最下部「4.ログイン画面の作成」をご覧ください。

新規登録画面イメージ

新規登録フォームの完成イメージを上図に示します。今回の例では、ユーザーID、メールアドレス、パスワード、氏名(苗字・名前)、プロフィール写真を項目として表示します。各項目名称は用途に応じて変更可能です。項目の定義方法は後述します。

システム挙動イメージ

新規登録フォームのシステム挙動も概略を掴んでおきましょう!新規登録フォームから送信ボタンを押すと、ユーザー情報がデータベースに登録される仕様を検討します。

ディレクトリ構成

最後にディレクトリ構成の確認です。下記のPythonスクリプト及びHTML&CSSファイルが編集対象です。

  • モデルクラス登録:models.py
  • アカウント新規登録フォーム:forms.py
  • 画面表示定義:views.py
  • 画面表示定義:urls.py
  • 各種設定:settings.py
  • 画面デザイン:各種HTML&CSSファイル

ユーザー新規登録画面作成プロセス

新規アカウント登録画面のコーディングを行なっていきます。作業手順の全体像は上図に該当します。

以下順を追って解説します。

【Django実践】事前設定|settings.py

この見出しではsettings.pyの修正方法について解説します。

  • フォルダのパス設定
  • パスワードのハッシュ化設定

フォルダのパス設定

フォルダのパス設定が既にお済みの場合、こちらはスキップいただいて問題ありません。未済の場合は前述したディレクトリ構成に基づき、パスを設定していきます。

settings.pyを開き、以下コーディングします。Template(HTML)、static(CSS)、及びmedia(画像)フォルダのディレクトリ指定が目的です。

※setting.spyでのディレクトリ設定は、Djangoバージョンによってやり方が異なります。バージョンに沿った方法で対応下さい。

続いて、settings.py内のTEMPLATESリストを見つけ、以下記載しましょう。

DIRS’: [TEMPLATE_DIR]とテンプレートのディレクトリを指定した点がデフォルトからの変更点です。

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [TEMPLATE_DIR,],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

続いて、static(CSS)フォルダとmedia(画像)フォルダのディレクトリを指定します。settings.py下部に移動し、以下のようにコーディングしましょう。ここでmediaフォルダとは、アカウント新規登録画面で登録された画像を格納するためのフォルダを意味します。

# Static files
STATIC_URL = '/static/'
STATICFILES_DIRS = [STATIC_DIR,]

#MEDIA_DIR
MEDIA_ROOT = MEDIA_DIR
MEDIA_URL = "/media/"

これにてディレクトリ設定は完了です!

パスワードハッシュ化設定

続いて、パスワードの強度およびハッシュ化設定を行います。

ハッシュ化とは、パスワードのような文字列をハッシュ関数で定められたルールに基づき、別の値に変換することを意味します。例えば、パスワード「tanaka01」をハッシュ化のルールに基づき、「QX837-dfz983o089-po24r」に置き換えることを意味します。

パスワードをデータベースで管理する際、セキュリティ上の理由からハッシュ化の検討は必須と言えます。万が一ハッキングでパスワードが流出しても、パスワードがハッシュ化されていれば、第三者によるパスワード復元を阻止できるためです。

それではコーディングです!まず、settings.py内にてPASSWORD_HASHERSというリストを見つけ、以下のように記載しましょう。

# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
PASSWORD_HASHERS = [
    "django.contrib.auth.hashers.Argon2PasswordHasher",
    "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
    "django.contrib.auth.hashers.BCryptPasswordHasher",
    "django.contrib.auth.hashers.PBKDF2PasswordHasher",
    "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
]

続いて、パスワードの強度を定義するために、以下のように記載します。

今回の例では、settings.py内にデフォルトで記載されているMinimumLengthValidatorを編集してみます。

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        'OPTIONS':{"min_length":6},
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

下記部分に数値を入力しパスワードの最小単位を設定しています。例えば、”min_length”:6と記載すると、最小6桁のパスワードのみ登録許可されます。

'OPTIONS':{"min_length":パスワードの最小単位を入力}

これにてsettings.pyでの設定は完了です!

【Django実践】モデル作成・データベース設定|models.py

アプリケーション管理フォルダ内のmodels.pyを開き、モデルクラスを登録します。新規アカウント登録画面からデータベースに登録する項目として、以下のようにフィールドを定義してみましょう。

from django.db import models
# ユーザー認証
from django.contrib.auth.models import User

# ユーザーアカウントのモデルクラス
class Account(models.Model):

    # ユーザー認証のインスタンス(1vs1関係)
    user = models.OneToOneField(User, on_delete=models.CASCADE)

    # 追加フィールド
    last_name = models.CharField(max_length=100)
    first_name = models.CharField(max_length=100)
    account_image = models.ImageField(upload_to="profile_pics",blank=True)

    def __str__(self):
        return self.user.username

上記について、ポイント毎に解説します。まず、重要な点は、Djangoのユーザー認証用のモジュール(User)を用いることです。Userをもとにインスタンスを作成すると、デフォルトとしてユーザー名、パスワード、メールアドレスというフィールドが指定できるようになります。

# ユーザー認証
from django.contrib.auth.models import User

今回ユーザーインスタンス(User)に加え、氏名(苗字、名前)、プロフィール写真をアップロードするためのフィールドを定義してみました。作成したい新規アカウント登録画面の必要項目に応じてフィールドを柔軟に定義してみましょう。

# ユーザー(ユーザー名、パスワード、メールアドレス)
user = models.OneToOneField(User, on_delete=models.CASCADE)

# 追加フィールド
last_name = models.CharField(max_length=100)
first_name = models.CharField(max_length=100)
account_image = models.ImageField(upload_to="profile_pics",blank=True)

モデルクラス記載後は、データベースへの適用処理が必要です。データベースに適用するために、マイグレーションを実行しましょう。

マイグレーションの実行方法について知りたい方は、こちらをご覧ください。

【Django実践】登録フォーム作成|forms.py

続いて、新規アカウント登録フォームの表示項目を定義していきます。forms.pyをアプリケーション管理フォルダ内に作成し、以下のようにコーディングしましょう。

先ほどモデルクラス(models.py)で登録したフィールドをそのままforms.pyに継承し、フィールドを定義することとします。

from django import forms
from django.contrib.auth.models import User
from .models import Account

# フォームクラス作成
class AccountForm(forms.ModelForm):
    # パスワード入力:非表示対応
    password = forms.CharField(widget=forms.PasswordInput(),label="パスワード")

    class Meta():
        # ユーザー認証
        model = User
        # フィールド指定
        fields = ('username','email','password')
        # フィールド名指定
        labels = {'username':"ユーザーID",'email':"メール"}

class AddAccountForm(forms.ModelForm):
    class Meta():
        # モデルクラスを指定
        model = Account
        fields = ('last_name','first_name','account_image',)
        labels = {'last_name':"苗字",'first_name':"名前",'account_image':"写真アップロード",}

ここで、AccountFormクラスではユーザー認証によるフィールドを定義し、AddAccountFormではDjangoのユーザー認証システム(User)で指定されていないフィールドを定義しました。

ユーザーがパスワード入力時、第三者に見えないよう「*******」と表示するために、下記の一文を記載しています。

# パスワード入力:非表示対応
password = forms.CharField(widget=forms.PasswordInput(),label="パスワード")

これにて新規アカウント登録フォームの項目定義は完了です!

【Django実践】画面表示設定|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
from django.http import HttpResponseRedirect, HttpResponse
from django.urls import reverse

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つずつ解説していきます。

まず、新規アカウント登録画面のパラメーターとして以下を定義しました。登録フォームへの表示項目として、forms.pyで定義したAccountForm()、AddAccountForm()クラスを指定します。

ユーザーがアカウント作成を試みた際、アカウント作成可否を判断するために、AccountCreateという真偽値を準備しています。

 "AccountCreate":False,
 "account_form": AccountForm(),
 "add_account_form":AddAccountForm(),

新規アカウント登録フォーム上でPOST処理が適用された場合、以下の対応を実施しています。

  1. アカウント登録情報に誤入力がないか検証
  2. アカウント登録情報をデータベースに保存
  3. データベース保存の際、パスワードはハッシュ化
  4. 画像が登録された場合、mediaフォルダ内に格納

これにてviews.pyによる画面表示設定は完了です!

【Django実践】フロント画面作成

アカウント新規登録画面作成(register.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>

 {% if AccountCreate %}
   <h1>登録完了!</h1>

 {% else %}
   <div class="reg">
   <table class="reg_form">

   <form enctype="multipart/form-data" method="post">
   {% csrf_token %}
   {{ account_form.as_table }}
   {{ add_account_form.as_table }}
   <tr><td></td><td>
   <input class="btn" type="submit" name="" value="登録">
   </td></tr>
   </form>

   </table>
   </div>
 {% endif %}

</body>
</html>

画面デザイン(style.css)

新規アカウント登録画面におけるCSSデザイン例を下記に示します。

h1{
  text-align: center;
}

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

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;
}

【Django実践】画面表示設定|urls.py

新規アカウント登録画面のURLマッピングを行います。

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

本記事でのURLマッピング方法としては、アプリケーションフォルダに作成したurls.pyに基づき、対象アプリケーション画面URLを管理します。

プロジェクト管理フォルダ内のurls.pyに対してinclude関数を用い、アプリケーション管理フォルダのurls.py記載のURLを指定します。この対応は、既にURL管理体系が決まっている場合、対応不要です。

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

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

]

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

アプリケーションフォルダのurls.pyを開き、以下記載しましょう。

from django.urls import path
from . import views

urlpatterns = [
    path('', views.AccountRegistration.as_view(), name='register'),
]

これにてurls.pyに基づくURLマッピング・画面表示設定は完了です!

管理画面設定(admin.py)

アカウント登録画面から登録ユーザーを管理画面から確認できるようにします。アプリケーション管理フォルダ内のadmin.pyを開き、以下記載しましょう。

from django.contrib import admin

from .models import Account
admin.site.register(Account)

ユーザーアカウント新規登録実践

これにてコーディングは全て完了です!お疲れ様でした。最後に実際に画面を見ながら動作確認してみましょう。

ターミナルを開き、以下入力し、ローカルサーバーへアクセスします。

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

新規アカウント登録画面から適時情報を入力し、アカウント登録してみましょう。

登録後、アカウント情報がデータベースに登録されていれば完成です!管理画面を開き確認してみましょう。

ログイン画面の作成

今回はアカウントのログイン画面に必要な新規登録フォームの作成方法について詳しく解説しました。

下記の記事では、ログイン画面の作成手順も記載しております。是非ご覧ください。

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

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

Django学習に最適!

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

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

最後に

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

本記事をシェア!
目次