Django+Pythonでパスワードリセットを実装する+viewカスタイズ 

## 環境
Windows11
Python 3.10.5
Django 4.2.7

## 経緯
Django+Pythonで学習がてらBlog作成中、パスワードリセット機能もつけたいと思い。

## views.py
    class PasswordReset(PasswordResetView):
        # パスワードリセット用URLの送信ページ
        success_url = reverse_lazy("blogapp:password_reset_done")
        # パスワード変更URL付きメールのカスタマイズ
        email_template_name = "blogapp/password_reset_email.html"
        template_name = "blogapp/password_reset_form.html"
    
    
    class PasswordResetDone(PasswordResetDoneView):
        # パスワード変更用URL送信完了ページ
        template_name = "blogapp/password_reset_done.html"
    
    
    class PasswordResetConfirm(PasswordResetConfirmView):
        # 新パスワード入力用ページ
        success_url = reverse_lazy("blogapp:password_reset_complete")
        template_name = "blogapp/password_reset_confirm.html"
    
    
    class PasswordResetComplete(PasswordResetCompleteView):
        # 新パスワード設定完了ページ
        template_name = "blogapp/password_reset_complete.html"

## urls.py
    app_name = "blogapp"
    urlpatterns = [
        path(
            "password_reset/",
            PasswordReset.as_view(),
            name="password_reset",
        ),
        path(
            "password_reset/done/",
            PasswordResetDone.as_view(),
            name="password_reset_done",
        ),
        path(
            "reset/<uidb64>/<token>/",
            PasswordResetConfirm.as_view(),
            name="password_reset_confirm",
        ),
        path(
            "reset/done/",
            PasswordResetComplete.as_view(),
            name="password_reset_complete",
        )
    ]
## password_reset_form.html
パスワードリセット用メール送信ページ

    {% extends "blogapp/base.html" %}
    {% load static %}
    
    {% block content %}
        <h1>Reset password</h1>
        <form method="POST">
        {% csrf_token %}
            {{ form.as_p }}
            <p><input type="submit" value="Send Mail"></p>
        </form>
    {% endblock %}

## password_reset_done.html
パスワードリセットメール送信完了ページ

    {% extends "blogapp/base.html" %}
    {% load static %}
    
    {% block content %}
        <h1>Email transmission comlete</h1>
        <p>Check your email</p>
    {% endblock %}

## password_reset_confirm.html
新しいパスワード設定ページ

    {% extends "blogapp/base.html" %}
    {% load static %}
    
    {% block content %}
    {% if validlink %}
        <h1>Set a new Password</h1>
        <form method="POST">
        {% csrf_token %}
            {{ form.as_p }}
            <p><input type="submit" value="Change password"></p>
        </form>
    {% else %}
        <p>The password reset link is invalid. It may have already been used.</P>
    {% endif %}
    
    {% endblock %}

## password_reset_complete.html
新しいパスワード設定完了ページ

    {% extends "blogapp/base.html" %}
    {% load static %}
    
    {% block content %}
        <h1>Change password complete</h1>
    {% endblock %}

## password_reset_email.html
パスワード変更用URL付きメールのカスタマイズ
Reverse for 'password_reset_confirm' with keyword arguments '{'uidb64': '', 'token': ''}' not found. 1 pattern(s) tried: ['reset/(?P<uidb64>[^/]+)/(?P<token>[^/]+)/\\Z']
このエラーが最初何か理解できなかった💦
このテンプレートの内容はDjangoのエラーページのをコピペしてpassword_reset_confirm部分を変更しています。
(url app_name:password_reset_confirm)

    {% load i18n %}{% autoescape off %}
    {% blocktranslate %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktranslate %}
    
    {% translate "Please go to the following page and choose a new password:" %}
    {% block reset_link %}
    {{ protocol }}://{{ domain }}{% url 'blogapp:password_reset_confirm' uidb64=uid token=token %}
    {% endblock %}
    {% translate 'Your username, in case you’ve forgotten:' %} {{ user.get_username }}
    
    {% translate "Thanks for using our site!" %}
    
    {% blocktranslate %}The {{ site_name }} team{% endblocktranslate %}
    
    {% endautoescape %}

## Runserverで確認
#### パスワードリセットページにアクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3587032/658a40e1-4aa6-b926-b799-e20a52d18a9c.png)

#### Send Mailすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3587032/41caa750-d362-968e-100e-d88ef599cb72.png)

#### メールのデバッグはsettings.pyに下記を追加
    EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"

#### 送信完了ページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3587032/fd226543-787d-1243-07df-6880c2eeedc8.png)

#### メールのURLにアクセスすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3587032/fb2eec1e-9e9c-87d6-b363-eecc610c152d.png)

#### 新しいパスワードを設定して完了すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3587032/f9c521ea-01b8-0bcd-59b6-dab4d5cf2b2e.png)

## まとめ
Djangoは楽しいですね。まだまだ全然わからないことのが多いですが💦
もっと色々できたら楽しそうです。
あと、このままではダサいのでCSSを作成して見栄え良くしていこうと思います。

## 参考サイト
https://stackoverflow.com/questions/49086882/reverse-for-password-reset-confirm-not-found-password-reset-confirm-is-not