みなさんこんにちは、ZeroTerasu(@ZeroTerasu)です。
Djangoでユーザー登録機能を実装する方法の2回目の今回は、「②”AbstractUser”モデルを継承する方法」を解説します。AbstractUserモデルを継承してカスタムユーザークラスを作成します。Django公式ドキュメントでもカスタムユーザーの使用が推奨されています。
因みに、第1回の「①Djangoデフォルトの”User”を使用する方法」ではフィールドの追加・削除が難しいため、これらの操作をする場合は今回の記事が参考になると思います。
尚、今回は下記の設定で進めていきます。
プロジェクト名とアプリ名
プロジェクト名=”pj”
アプリ名=”registration”
今回の内容はこちらです。
ポイント①:AbstractUserモデルを継承してカスタムユーザーを作成。
ポイント②:settings.pyで”AUTH_USER_MODEL”の設定。
ポイント③:UserCreationFormを継承してフォームを作成。
ポイント④:CreateView を継承してユーザー登録機能ビューを作成。
ポイント➄:URLパターンの設定。ログイン必須ページには、ビューにlogin_required()をデコレートする。
ポイント⑥:テンプレートの作成
アプリの概要説明
下記のような流れでユーザー登録機能を実装していきます。
①トップページからユーザー登録ページへ移動。
②ユーザー登録とログインを同時に実行する。
③ログイン後ページに遷移する。

・トップページには「登録ページ」と「ログイン後ページ」のリンク先を設定します。
↓

・仮にログインしていない状態でログイン後ページにアクセスしようとするとエラーが表示されるようにしています。
↓

・forms.pyでSignUpForm内に設定したフィールドが表示されるようになっています。
↓

・ユーザー登録が無事に完了した後、自動的にログインされ、フォームに入力したデータがテンプレートに渡され表示されます。
ポイント①:AbstractUserモデルを継承してカスタムユーザーを作成。
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class User(AbstractUser):
# 1.フィールドの修正:フィールドをオーバライド。
email = models.EmailField(verbose_name='メールアドレス', unique=False, blank=True)
# 2.フィールドの追加
gendar = models.CharField(verbose_name='性別',max_length=10)
favorite_url = models.URLField(verbose_name='お気に入りURL', max_length=300, blank=True, null=True)
# ユーザー作成時に必須となるフィールドのリストを指定
REQUIRED_FIELDS = ['gendar']
1. フィールドの修正方法:既存のフィールドをオーバーライド
2. フィールドの追加方法:新規フィールドを追加
※ 必須フィールドの指定:REQUIRED_FIELDSの指定
ポイント②:settings.pyで”AUTH_USER_MODEL”の設定。
# 変更箇所-1
INSTALLED_APPS = [
'registration', #<=追加
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
# 変更箇所-2
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'], #<=追加
'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',
],
},
},
]
# 変更箇所-3
LANGUAGE_CODE = 'ja' #<=デフォルトでは、'en-us'になっていますが、日本語に変更します。
# 変更箇所-4
AUTH_USER_MODEL = 'registration.User'
ポイント③:UserCreationFormを継承してフォームを作成。
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import get_user_model
User = get_user_model()
GENDER_CHOICES = [
# 最初の要素が実際の値、2番目の要素が表示されるラベルです。
('男性', '男性'),
('女性', '女性'),
('その他', 'その他')
]
class SignUpForm(UserCreationForm):
gendar = forms.ChoiceField(label='性別',choices=(GENDER_CHOICES))
class Meta:
model=User
fields = ['username', 'email', 'password1', 'password2', 'gendar', 'favorite_url']
・UserCreationFormは、Djangoが提供するデフォルトのフォームクラスの1つです。このフォームは、ユーザーの新規登録(ユーザー作成)に使用されます。UserCreationFormは、ユーザー名、パスワード、パスワードの確認など、一般的なユーザー作成に必要なフィールドを提供します。
・UserCreationFormはデフォルトでユーザーモデル(User)を対象としています。カスタムユーザーモデルを使用している場合は、それに合わせてフォームをカスタマイズする必要があります。(別記事にて解説致します。)
username: ユーザー名を入力するフィールドです。入力必須項目です。一意である必要があります。(他のユーザーとこのフィールド名が被ってはいけません。)
email: メールアドレスを入力するフィールドです。入力は任意です。
password1: パスワードを入力するフィールドです。パスワードはセキュアにハッシュ化され保存されます。
password2: パスワードを再入力するフィールドです。このフィールドはpassword1と一致する必要があります。
・fieldsには、リスト形式またはタプル形式で使用するフィールドを渡します。
・必要に応じて独自のフィールドを追加することもできます。カスタムフィールドを追加する場合は、UserCreationFormを継承し、新しいフィールドを追加するクラスを作成することができます。
ポイント④:CreateView を継承してユーザー登録機能ビューを作成。
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
from django.contrib.auth import get_user_model
# Create your views here.
class IndexView(TemplateView):
template_name='registration/index.html'
class HomeView(TemplateView):
template_name='registration/home.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.object = user
# get_success_url()メソッドを使用してリダイレクト先のURLを取得し、HttpResponseRedirectを使用してそのURLにリダイレクトします。
return HttpResponseRedirect(self.get_success_url())
上記のビューでは、ユーザーの新規登録を処理し、登録後にユーザーをログインさせて指定されたURLにリダイレクトさせています。
まず、CreateViewを継承してSignUpViewというクラスを定義し、ユーザーの新規登録・ログインを処理します。
・form_valid(self, form): form_valid()メソッドは、フォームのデータが有効である場合に呼び出されます。このメソッドでは、フォームのデータを保存し、ユーザーをログインさせてリダイレクトする処理が行われます。
ポイント➄:URLパターンの設定。ログイン必須ページには、ビューにlogin_required()をデコレートする。
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('registration.urls')),
path('admin/', admin.site.urls),
]
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を引数として内包する。
ポイント⑥:テンプレートの作成
①トップページ:index.html → ②登録ページ:signup.html → ③ログイン後ページ:home.html
<!DOCTYPE html>
<html lang="en">
<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">
<title>Index</title>
</head>
<body>
<div style="margin: 0 auto; width: 1100px;">
<h1>トップページ</h1><br>
<a href="{% url 'registration/signup' %}">ユーザー登録ページのリンク先です。</a><br>
<a href="{% url 'registration/home' %}">ログイン後ページのリンク先です。(ログインしていない状態では入れません。)</a>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<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">
<title>signup</title>
</head>
<body>
<div style="margin: 0 auto; width: 1100px;">
<h1>登録フォーム</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="登録">
</form>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<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">
<title>Home</title>
</head>
<body>
<div style="margin: 0 auto;">
<h1>ユーザー詳細ページ</h1>
<table border="1" rule="all" style="border: 1px solid black; border-collapse: collapse;">
<tr>
<th>username</th>
<th>email</th>
<th>gendar</th>
<th>favorite_url</th>
</tr>
<tr>
<td>{{ user.username }}</td>
<td>{{ user.email }}</td>
<td>{{ user.gendar }}</td>
<td>{{ user.favorite_url }}</td>
</tr>
</table>
</div>
</body>
</html>
コメント