みなさんこんにちは、ZeroTerasu(@ZeroTerasu )です。
今回から3回に渡りDjangoでのユーザー登録機能の実装方法について解説していきます。
Djangoでユーザー登録機能を実装する方法 は、Userモデルの使い方によって3種類の方法 があります。
Userモデル別Djangoでのユーザー登録機能の実装方法
Userモデル別Djangoでのユーザー登録機能の実装方法
①Djangoデフォルトの”User”を使用する方法
②”AbstractUser”を継承する方法
③”AbstractBaseUser”と”PermissionsMixin”を継承する方法
上記のUserモデルの継承関係は下記のようになります。
ユーザー登録機能に関連するUserモデルの継承関係
①Userモデル(自由度=低):
Djangoのデフォルトのユーザーモデルです。django.contrib.auth.modelsモジュール内に定義されており、多くの場合、通常のウェブアプリケーションで必要な基本的なユーザー情報を提供します。Userモデルは、ユーザー名、パスワード、メールアドレスなど、基本的な認証と関連するフィールドを持っています。
②AbstractUserモデル(自由度=中):
AbstractUserは、Userモデルの抽象クラスであり、Userモデルのカスタマイズや拡張を容易にするために提供されています。AbstractUserを継承して新しいユーザーモデルを作成することで、追加のフィールドやメソッドを追加することができます。例えば、AbstractUserを継承して電話番号やプロフィール画像のフィールドを追加したり、カスタムの認証ロジックを実装したりすることができます。
③AbstractBaseUserモデル(自由度=高):
AbstractBaseUserは、最も抽象度が高いユーザーモデルです。django.contrib.auth.modelsモジュール内に定義されています。AbstractBaseUserは、最低限の認証機能を提供する最小限のユーザーモデルを定義するために使用されます。具体的なフィールドは定義されていないため、必要な属性やメソッドを独自に実装する必要があります。AbstractBaseUserを使用する場合、ユーザーモデルのカスタマイズや拡張には多くの作業が必要ですが、柔軟性が高く、より高度な要件に対応することができます。
第一回の今回は、「①Djangoデフォルトの”User”を使用する方法 」について解説していきます。
尚、今回は下記の設定で進めていきます。
プロジェクト名とアプリ名
プロジェクト名=”pj”
アプリ名=”registration”
今回の内容はこちらです。
今回の内容
ポイント①:モデルにはDjangoデフォルトのUserを使用。(models.pyでのモデル定義は不要)
ポイント②:UserCreationFormを継承してフォームを作成。
ポイント③:CreateView を継承してユーザー登録ビューを作成。
ポイント④:URLパターンの設定。ログイン必須ページには、ビューにlogin_required()をデコレートする。
ポイント➄:テンプレートの作成
アプリの概要説明
アプリの内容
下記の3ステップのような流れでユーザー登録機能を実装していきます。
トップページ
・トップページには登録ページへのリンク先を設定します。
↓
登録ページ
・forms.pyでSignUpForm内に設定したフィールドが表示されるようになっています。
↓
ログイン成功ページ
・ユーザー登録が無事に完了した後、ユーザー名が表示されるようにしています。
DjangoデフォルトのUserモデルに実装されているフィールド
DjangoデフォルトのUserモデルには下記のフィールドが標準で実装されています。これらのフィールドを追加・変更・削除するためには、次回以降で解説するカスタムユーザーを定義する必要があります。
DjangoデフォルトのUserモデルに実装されているフィールド
No. フィールド名 解説 主な属性 1 username ユーザー名を表す文字列フィールドです。 ・unique=True: ユーザー名は一意である必要があります。 ・blank=False: 空の値は許可されません。 2 password パスワードを表す文字列フィールドです。 blank=False: 空の値は許可されません。 3 email メールアドレスを表す文字列フィールドです。 ・unique=True: メールアドレスは一意である必要があります。 ・blank=False: 空の値は許可されません。 4 first_name ユーザーの名を表す文字列フィールドです。 blank=True: 空の値が許可されます。 5 last_name ユーザーの姓を表す文字列フィールドです。 blank=True: 空の値が許可されます。 6 is_staff スタッフメンバーであるかどうかを示す真偽値フィールドです。管理サイトへのアクセスを許可します。 False: デフォルトではスタッフメンバーではありません。 7 is_active アカウントが有効化されているかどうかを示す真偽値フィールドです。アカウントが無効になっている場合、ユーザーはログインできません。 True: デフォルトではアカウントは有効です。 8 is_superuser スーパーユーザーであるかどうかを示す真偽値フィールドです。全ての権限を持ちます。 False: デフォルトではスーパーユーザーではありません。 9 last_login 最後にログインした日時を表す日時フィールドです。 blank=True: 空の値が許可されます。 10 date_joined アカウントが作成された日時を表す日時フィールドです。 default=timezone.now: デフォルト値は現在の日時です。
ポイント①:モデルにはDjangoデフォルトのUserを使用。(models.pyでのモデル定義は不要)
・DjangoデフォルトのUserモデルを使用する場合は、別途Userモデルを定義する必要はありません。
ポイント②:UserCreationFormを継承してフォームを作成。
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class SignUpForm(UserCreationForm):
class Meta:
model = User
fields=["username", "email", "password1", "password2"]
UserCreationForm
・UserCreationForm は、Djangoが提供するデフォルトのフォームクラスの1つです。このフォームは、ユーザーの新規登録(ユーザー作成) に使用されます。UserCreationFormは、ユーザー名 、パスワード 、パスワードの確認 など、一般的なユーザー作成に必要なフィールドを提供します。
・UserCreationForm はデフォルトでユーザーモデル(User) を対象としています。カスタムユーザーモデルを使用している場合は、それに合わせてフォームをカスタマイズする必要があります。(別記事にて解説致します。)
UserCreationFormの 主要 フィールド一覧
username : ユーザー名を入力するフィールドです。入力必須項目です。一意である必要があります。(他のユーザーとこのフィールド名が被ってはいけません。)
email : メールアドレスを入力するフィールドです。入力は任意です。
password1 : パスワードを入力するフィールドです。パスワードはセキュアにハッシュ化され保存されます。
password2 : パスワードを再入力するフィールドです。このフィールドはpassword1と一致する必要があります。
・fieldsには、リスト形式またはタプル形式で使用するフィールドを渡します。
・必要に応じて独自のフィールドを追加することもできます。カスタムフィールドを追加する場合は、UserCreationFormを継承し、新しいフィールドを追加するクラスを作成することができます。
ポイント③:CreateView を継承してユーザー登録ビューを作成。
views.py
from django.shortcuts import render
from django.http.response import HttpResponseRedirect
from django.views.generic import TemplateView
from django.views.generic.edit import CreateView
from .forms import SignUpForm
from django.contrib.auth import login
from django.urls import reverse_lazy
# Create your views here.
class IndexView(TemplateView):
template_name='registration/index.html'
class SignUpView(CreateView):
form_class=SignUpForm # form_class属性は、ビューで使用されるフォームクラスを指定します。この例では、'SignUpForm'というフォームクラスが使用されます。
template_name='registration/signup.html' # template_name属性は、ビューで使用されるテンプレートのパスを指定します。この例では、'app/signup.html'というテンプレートが使用されます。
success_url=reverse_lazy('registration/home.html') # success_url属性は、フォームの送信後にリダイレクトされるURLを指定します。reverse_lazy()関数を使用して逆引き解決されたURLを指定しています。この例では、'app/home.html'というURLにリダイレクトされます。
def form_valid(self, form):
# form.save()メソッドを使用してフォームのデータを保存し、新しいユーザーオブジェクトを取得します。
user=form.save()
# login()関数を使用して、self.requestオブジェクトと保存されたユーザーオブジェクトを使用してユーザーをログインさせます。
login(self.request, user)
# self.object属性に保存されたユーザーオブジェクトを設定します。これにより、ビュー内でユーザーオブジェクトにアクセスできます。
self.objecct = user
# get_success_url()メソッドを使用してリダイレクト先のURLを取得し、HttpResponseRedirectを使用してそのURLにリダイレクトします。
return HttpResponseRedirect(self.get_success_url())
コード解説
上記のビューでは、ユーザーの新規登録を処理し、登録後にユーザーをログインさせて指定されたURLにリダイレクトさせています。
まず、CreateView を継承してSignUpView というクラスを定義し、ユーザーの新規登録 ・ログインを処理 します。
・form_valid(self, form) : form_valid()メソッドは、フォームのデータが有効である場合に呼び出されます。このメソッドでは、フォームのデータを保存し、ユーザーをログインさせてリダイレクトする処理が行われます。
pj/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('registration.urls')),
path('admin/', admin.site.urls),
]
ポイント④:URLパターンの設定。ログイン必須ページには、ビューにlogin_required()をデコレートする。
pj/registration/urls.py
from django.urls import path
from . import views
from django.contrib.auth.decorators import login_required
urlpatterns = [
path('', views.IndexView.as_view(), name='registration/index'),
path('signup/', views.SignUpView.as_view(), name='registration/signup'),
path('home/', login_required(views.HomeView.as_view()), name='registration/home'),
]
コード解説
・ログイン必須ページには、login_required()メソッドを使い、対象のviewを引数として内包する。
ポイント➄:テンプレートの作成
pj/templates/registration/index.html
{% extends 'registration/base.html' %}
{% block page-nav %}トップページ{% endblock %}
{% block main %}
<a href="{% url 'registration/index' %}">トップページのリンク先です。</a>
<a href="{% url 'registration/signup' %}">登録ページのリンク先です。</a>
{% endblock %}
pj/templates/registration/base.html
<!DOCTYPE html>
<html lang="ja">
<head>
{% include 'registration/_head.html' %}
</head>
<body>
{% include 'registration/_header.html' %}
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a href="/" class="navbar-brand">{% block page-nav %}{% endblock %}</a>
</nav>
{% block main %}
{% endblock %}
{% include 'registration/_footer.html' %}
</body>
</html>
pj/templates/registration/_form.html
<div class="container mt-4">
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="{{ value }}" class="btn btn-info">
</form>
</div>
pj/templates/registration/signup.html
{% extends 'registration/base.html' %}
{% block page-nav %}登録ページ{% endblock %}
{% block main %}
{% include 'registration/_form.html' with value='登録' %}
{% endblock %}
コメント