「メール認証付きユーザー登録機能」をdjangoで実装する

2022年5月3日

「メール認証付きユーザー登録機能」をdjangoで実装する

djangoでは「管理画面」や「ログイン機能」などもともとウェブアプリで必要な機能がそろっています。今回はdjangoの「django-allauth」を使って下記の機能を実装したいと思います。
・サインアップ
・ログイン/ログアウト
・パスワードリセット
・メールアドレス認証

インストール

django-allauthをインストールします。


pip3 install django-allauth

階層

階層は下の通りです。


.
├── accounts
│   ├── templates #3
│   │   └── account
│   │       ├── email #4
│   │       │   ├── email_confirmation_message.txt
│   │       │   ├── email_confirmation_subject.txt
│   │       │   ├── password_reset_key_message.txt
│   │       │   └── passwword_reset_key_subject.txt
│   │       ├── email_confirm.html
│   │       ├── login.html
│   │       ├── password_reset_done.html
│   │       ├── password_reset_from_key.html
│   │       ├── password_reset.html
│   │       └── signup.html
│   ...
│   
├── blog
├── config
│   ├── settings.py #1
│   ├── urls.py #2
...

1 - メールの設定とアカウントの設定をします。

2 - django-allauthのルーティングを設定します。

3 - 上記の通りにテンプレートを作成する事でデフォルトのテンプレートを上書きできます。

4 - 認証の際のメールの定型文を設定します。

メールとアカウントの設定

settings.pyに下記を追記していきます。
説明はコメントアウトで直接記載しております。
「メール」の設定は以前書かせて頂いたこちらを参照頂ければと思います。
※「allauth.socialaccount」はテンプレートを上書きしない場合入れておかないとエラーが出るのでいれています。


INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'accounts.apps.AccountsConfig',
    'blog.apps.BlogConfig',
    'widget_tweaks',
    'django.contrib.sites',#追記
    'allauth', #追記
    'allauth.account', #追記
    'allauth.socialaccount', #追加
]
...
(略)
...
#ここから下すべて追記
#--メール---------------------------------------------------
#コンソールに表示
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# 実際にメールを送信
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
#メールサーバーへの接続設定
DEFAULT_FROM_EMAIL = 'your_mail.bm@gmail.com'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'your_mail@gmail.com'
EMAIL_HOST_PASSWORD = 'google_account_application_passwd'
EMAIL_USE_TLS = True
#--アカウント認証設定------------------------------------------
#django-allauthで利用するdjango.contrib.sitesを使うためにサイト識別用IDを設定
SITE_ID = 1
#認証バックエンド-ログイン時に何でログインするかを配列の先頭から順に認証する
AUTHENTICATION_BACKENDS = (
    #メールアドレス認証
    'allauth.account.auth_backends.AuthenticationBackend',
    #ユーザー名認証
    'django.contrib.auth.backends.ModelBackend',
)
#メールアドレス認証に変更する設定
ACCOUNT_AUTHENTICATION_METHOD = 'email'
#ユーザー名の入力を必要とする設定
ACCOUNT_USERNAME_REQUIRED = True
#サインアップにメールアドレス確認をはさむよう設定
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
ACCOUNT_EMAIL_REQUIRED = True
#ログイン/ログアウト後の遷移先を設定
LOGIN_REDIRECT_URL = 'xxx:index'
ACCOUNT_LOGOUT_REDIRECT_URL = 'account_login'
#ログアウトリンクのクリック一発でログアウトする設定
ACCOUNT_LOGOUT_ON_GET = True

ルーティングの設定

次に作成した「django-allauth」にアクセスできるようルーティングを設定してあげます。
「config/urls.py」に下記を追記してあげます。


urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('blog.urls')),
    path('accounts/', include('allauth.urls')), #追記
]

「accounts/」配下のURLは下の通りです。

URL 処理内容
/accounts/signup/ サインアップ(エントリー画面表示)
/accounts/confirm-email/ サインアップ(メール送信)
/accounts/confirm-email/<key>/ サインアップ(確定)
/accounts/login/ ログイン
/accounts/logout/ ログアウト
/accounts/password/reset/ パスワードリセット(エントリー画面表示)
/accounts/password/reset/done/ パスワードリセット(メール送信)
/accounts/password/reset/key/<key>-set-password/ パスワードリセット(パスワード設定)
/accounts/password/reset/key/done パスワードリセット(確定)

テンプレートの設定

テンプレートを下の通りに作成しデフォルトのテンプレートを上書きします。
【signup.html】


<h1>サインアップ</h1>
<form method="post" action="{% url 'account_signup' %}">
    {% csrf_token %}
    {{ form.as_p }}
    {% if redirect_field_value %}
        <input type="hidden" name="{{ redirect_field_name}}" value="{{ redirect_field_value }}" />
    {% endif %}
    <button type="submit">登録</button>
</form>

【email_confirm.html】


{% if confirmation %}
    <p>ユーザー登録を確定するには下のボタンを押してください。</p>
    <form method="post" action="{% url 'account_confirm_email' confirmation.key %}">
        {% csrf_token %}
        <button type="submit">確定</button>
    </form>
{% else %}
    {% url 'account_email' as email_url %}
    <p>リンクの有効期限が過ぎています。<a> href="{{ email_url }}"</a>.</p>
{% endif %}

【login.html】


<h1>Log In</h1>
<form method="post" action="{% url 'account_login' %}">
    {% csrf_token %}
    {{ form.as_p }}
    {% if redirect_field_value %}
    <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
    {% endif %}
    <button type="submit">ログイン</button>
    <p><a href="{% url 'account_reset_password' %}">パスワードを忘れましたか?</a></p>
</form>

【password_reset.html】


<h1>パスワードリセット</h1>
{% if user.is_authenticated %}
    {% include "accout/snippets/already_logged_in.html" %}
{% endif %}
<p>パスワード例セット用メールを送信します。</p>
<form method="post" action="{% url 'account_reset_password' %}">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">送信</button>
</form>

【password_reset_done.html】


<h1>パスワードリセット</h1>
{% if user.is_authenticated %}
    {% include "account/snippets/already_logged_in.html" %}
{% endif %}
<p>パスワードリセット用のメールを送信しました。</p>

【password_reset_from_key.html】


<h1>{% if token_fail %}不正トークン{% else %}パスワードリセット{% endif %}</h1>
{% if token_fail %}
    {% url 'account_reset_password' as passwd_reset_url %}
    <p>このパスワードリセット用リンクは無効になっています。<a href="{{ passwd_reset_url }}">パスワードリセット再申請</a></p>
{% else %}
    {% if form %}
        <form method="post" action="{{ action_url }}"> 
            {% csrf_token %}
            {{ form.as_p }}
            <button type="submit">変更</button>
        </form>
    {% else %}
        <p>パスワードは変更されています。</p>
    {% endif %}
{% endif %}

メールの定型文の設定

メールの定型文を作成してデフォルトのメールの定型文を上書きします。
【email_confirmation_message.txt】


ご登録ありがとうございます。
ご登録を続けるには、以下のリンクをクリックしてください。
{{ activate_url}}

【email_confirmation_subject.txt】


ユーザー登録確認メール

【password_reset_key_message.txt】


パスワードリセットが申請されました。処理を続けるには、以下のリンクをクリックしてください。
{{ password_reset_url }}

【passwword_reset_key_subject.txt】


パスワードリセット

感想

企業目線で見ると「管理画面」「アカウント機能」を爆速で作成できるdjangoはとても魅力的だと思います。AWSなどのクラウドサービスの利用、STRIPEを利用した決済システムの導入等今後は、便利なサービスやツールを使えるエンジニアの需要が高まりそうです。

2022年5月3日