「ユーザー管理用のアプリ」を作ってユーザー認証機能を集約したい!
このような方に向けて書きました。
django-allauthを使えば認証機能をまるっと実装できるので、愛用されている方も多いのではないでしょうか?
ところがdjango-allauthは多機能ゆえにプロジェクトが散らかってしまいがち。
そこでおすすめするのが、ユーザー管理用のアプリを作成することです。
本記事ではaccounts
アプリを作成してユーザー管理を行う方法をはじめ、これと関連したカスタマイズ方法も合わせてご紹介します。
accountsアプリで実装するための下準備
初めてでも進められるように、django-allauthのセットアップから解説します。
すでにdjango-allauthの環境が整っている方は、適宜読み飛ばしてください。
django-allauthの環境構築
django-allauthをインストールします。
pip install django-allauth
django-allauthを有効化するため、settings.pyに以下を記述します。
INSTALLED_APPS = [
# 追加
"django.contrib.sites",
"allauth",
"allauth.account",
"allauth.socialaccount",
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"allauth.account.middleware.AccountMiddleware", # 追加
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend",
"allauth.account.auth_backends.AuthenticationBackend",
]
SITE_ID = 1
プロジェクト側のurls.pyに次のコードを追加し、認証系のエンドポイントを一気に作成しましょう。
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
# django-allauthのエンドポイントを生成
path("accounts/", include("allauth.urls")),
]
この一文により、次のエンドポイントが作成されます。
エンドポイント | 名前空間 |
---|---|
accounts/login/ | account_login |
accounts/logout/ | account_logout |
accounts/password/change/ | account_change_password |
accounts/signup/ | account_signup |
accounts/confirm-email/ | account_confirm_email |
accounts/password/reset/ | account_confirm_email |
accounts/password/reset/ | account_reset_password |
accounts/password/reset/done/ | account_reset_password_done |
accounts/password/reset/key/<uidb36>-<key>/ | account_reset_password_from_key |
accounts/email/ | account_email |
accounts/social/connections/ | socialaccount_connections |
accountsアプリを作成
ユーザーを管理するaccounts
アプリを作成します。
まずはアプリを格納するディレクトリを作成。
mkdir -p apps/accounts
コマンドでaccounts
アプリを生成しましょう。
python manage.py startapp accounts apps/accounts
デフォルトだとurls.py
が生成されないので、作成しておきます。
touch apps/accounts/urls.py
Djangoにaccounts
アプリを認識させるため、INSTALLED_APPS
にアプリ名を追加。
INSTALLED_APPS = [
# 追加
"accounts.apps.AccountsConfig",
]
今回はapps
ディレクトリ配下にアプリを生成したので、apps.py
を修正しておきましょう。
from django.apps import AppConfig
class AccountsConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "apps.accounts" # 元々は name = "accounts" だった
プロジェクトのurls.py
にはaccounts
アプリへのルーティングを追加しておきましょう。
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("accounts/", include("accounts.urls")), # 追加
path("accounts/", include("allauth.urls")),
]
この際にはallauth.urls
より上に追加してください。
なぜなら、Djangoはurlpatters
を上から読み込むので、先にallauth.urls
を書いてしまうと追加したエンドポイントが読み込まれることがないからです。
なお、accounts
アプリは何も編集していないので、今の段階ではこのコード追加は無意味です。
後ほどご紹介するビューのカスタマイズなどで役に立ちます。
カスタムユーザーモデルの作成
accounts
アプリを作る目的は「ユーザー認証機能の集約」です。
その意味では、カスタムユーザーモデルを作ることはかなり重要な立ち位置であると言えます。
ここでは簡単に解説します。
カスタムユーザーについてもっと詳しく知りたい方は、次の記事も併せて読んでみてください。
» 参考:【Django】カスタムユーザーモデルの作り方【認証】
カスタムユーザーモデルを作成する
まずはmodels.py
でカスタムユーザーの定義を行います。
ここではシンプルにage
フィールドのみを追加しました。
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
# 追加のフィールドを定義
age = models.IntegerField(null=True, blank=True)
def __str__(self):
return self.username
ここではAbstractUser
を継承しています。
そのため、AbstractUser
で定義されているすべてのフィールドは保持されたままになります。
最後にDjangoでカスタムユーザーモデルを使うよう、settings.pyで指定します。
AUTH_USER_MODEL = "accounts.CustomUser"
カスタムユーザーに合わせたフォームを用意する
先ほどage
フィールドを追加したので、フォームにもage
フィールドとその保存ロジックを加えていきましょう。
from allauth.account.forms import SignupForm
from django import forms
class CustomSignupForm(SignupForm):
age = forms.IntegerField(required=False)
def save(self, request):
user = super(CustomSignupForm, self).save(request)
user.age = self.cleaned_data.get("age")
user.save()
return user
ここで継承しているSignupForm
はdjango-allauth標準のサインアップフォームです。
つまりage
フィールドは含まれていないので、ここで追加しています。
作成したサインアップフォームを有効化するため、settings.py
に以下を書き込みます。
ACCOUNT_FORMS = {"signup": "accounts.forms.CustomSignupForm"}
以上で簡単なカスタムユーザーモデルの作成は完了です。
その他のカスタマイズ
ユーザーモデル以外のカスタマイズ方法を解説します。
accountsアプリを作成する場合によく実装される内容ばかりなので、要件に応じて積極的に取り入れてみてください。
ビューをカスタマイズする方法
django-allauthで用意されている各エンドポイントに対して、ビューロジックを編集する方法をご紹介します。
django-allauthで用意されているビューを継承し、メソッドをオーバーライドします。
from allauth.account.views import SignupView
class CustomSignupView(SignupView):
def form_valid(self, form):
response = super().form_valid(form)
# フォームが有効な場合の追加処理をここに記述
return response
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# 必要に応じて追加のコンテキストデータをここで設定
context["extra_data"] = "Some extra data"
return context
def get_success_url(self):
# サインアップ成功後のリダイレクト先をカスタマイズする場合はここで設定
return super().get_success_url()
CustomSignupView
を有効化するため、アプリ側のurls.py
でルーティングを行いオーバーライドを有効にします。
from django.urls import path
from . import views
app_name = "accounts"
urlpatterns = [
path("signup/", views.CustomSignupView.as_view(), name="signup"),
]
これで基本的なビューロジックのカスタマイズは完了です。
ビューロジックのカスタマイズについて詳しく知りたい方は、別記事をどうぞ。
» 参考:【django-allauth】ビューロジックのカスタマイズ方法
テンプレートHTMLのカスタマイズ
settings.py
のDIRS
で、DjangoにテンプレートHTMLのありかを教えてあげます。
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [BASE_DIR / "templates"], # プロジェクトレベルのテンプレートディレクトリ
"APP_DIRS": True,
},
]
さらに、テンプレートHTMLをカスタマイズする場合には「しかるべき場所」にオーバーライド用のHTMLファイルを配置する必要があります。
例えばサインアップページなら、以下に配置します。
templates/accounts/signup.html
project_root/
└── templates/
└── accounts/
└── signup.html
最後にビューで先ほどのカスタムHTMLを読むように設定しましょう。
こちらで説明したようにカスタムビューの作成とurls.pyの変更をします。
その上で、template_name
に自分で作ったテンプレートHTMLを指定します。
class CustomSignupView(SignupView):
template_name = "accounts/custom_signup.html"
以上が基本的なテンプレートHTMLの作成方法です。
テンプレートHTMLのより詳しい内容は別記事で解説する予定です。(準備中)
【その他のテンプレートHTMLファイルを配置する場所】
project_root/
│
├── templates/
│ ├── base.html
│ │
│ ├── account/
│ │ ├── account_inactive.html
│ │ ├── email.html
│ │ ├── email_confirm.html
│ │ ├── login.html
│ │ ├── logout.html
│ │ ├── password_change.html
│ │ ├── password_reset.html
│ │ ├── password_reset_done.html
│ │ ├── password_reset_from_key.html
│ │ ├── password_reset_from_key_done.html
│ │ ├── password_set.html
│ │ ├── signup.html
│ │ ├── signup_closed.html
│ │ ├── verification_sent.html
│ │ └── verified_email_required.html
│ │
│ ├── socialaccount/
│ │ ├── authentication_error.html
│ │ ├── login_cancelled.html
│ │ ├── connections.html
│ │ ├── signup.html
│ │ └── snippets/
│ │ ├── provider_list.html
│ │ └── login_extra.html
│ │
│ └── custom_accounts/
│ └── profile.html
│
└── your_app/
└── templates/
└── your_app/
├── specific_template1.html
└── specific_template2.html
アダプターを使ったカスタマイズ
アダプターは、django-allauthの基本的な動作をカスタマイズするのに使われます。
例えば次のようなことができます。
- ユーザー作成時に追加のフィールドを処理する
- ログイン成功時に特定のアクションを実行する
- パスワード変更時のバリデーションルールを追加する
次の例は、「ユーザー作成時に追加のフィールドを処理する」ものです。
# accounts/adapters.py
from allauth.account.adapter import DefaultAccountAdapter
class CustomAccountAdapter(DefaultAccountAdapter):
def save_user(self, request, user, form, commit=True):
user = super().save_user(request, user, form, commit=False)
user.custom_field = form.cleaned_data.get("custom_field")
user.save()
return user
なお、アダプターを有効化するにはsettings.py
でカスタムアダプターを指定する必要があります。
# settings.py
ACCOUNT_ADAPTER = "accounts.adapters.CustomAccountAdapter"
アダプターについての詳しい説明は、別記事に譲りたいと思います。(準備中)
シグナルを使ったカスタマイズ
シグナルは、特定のイベントで自動発火する関数です。
django-allauthでは、ユーザー登録やログインなどのイベントに対してシグナルが発生します。
例えばサインアップ時に追加処理を行いたい場合は以下の通りです。
# accounts/signals.py
from allauth.account.signals import user_signed_up
from django.dispatch import receiver
@receiver(user_signed_up)
def after_user_signed_up(request, user, **kwargs):
# ユーザー登録後の追加処理
user.profile.create()
ここで作成したsignals.pyはapps.pyでインポートして信号を接続します。
# accounts/apps.py
from django.apps import AppConfig
class AccountsConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "apps.accounts"
def ready(self):
import accounts.signals # シグナルを読み込む
シグナルについて詳しくは別記事でご紹介する予定です。(準備中)
コメント