출처: https://meyouus.tistory.com/64 [정보 공유 - For Me For You For Us]
본문으로 바로가기

www.youtube.com/watch?v=sFPcd6myZrY&list=PL-51WBLyFTg2vW-_6XBoUpE7vpmoR3ztO&index=20

 

이 포스팅은 다음과 같은 youtube 영상을 따라하면서 배운 내용과 학습 내용을 담은 것이다:

  • Dennis Ivy - Password Reset Email | Django Framework (3.0) Crash Course Tutorials (pt 20)

현재 Django Version 3.1.2 를 쓰고 있다. Django는 파이썬을 쓰는 오픈소스 웹 프레임워크이다. 웹사이트 만들때 주로 쓰며, 간단한 것이 큰 특징이다.

 

(원래는 Introduction to Django Signals / Creating Customer Profiles with Django Signals 가 먼저 해야되는데 약간 다른 Topic이라 생각되어 Password Reset Email 부터 하기로 했다.)

 

※ urls.py 수정하기

우선, urls.py를 다음과 같이 수정한다:

# urls.py
from django.urls import path
from django.contrib.auth import views as auth_views
from . import views

urlpatterns = [
    ...
    path('reset_password/', auth_views.PasswordResetView.as_view(), name="reset_password"),
    path('pasword_reset_done/', auth_views.PasswordResetDoneView.as_view(), name="password_reset_done"),
    path('password_reset_confirm/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(), name="password_reset_confirm"),
    path('password_reset_complete/', auth_views.PasswordResetCompleteView.as_view(), name="password_reset_complete"),
    ...
	]

첫번째로, from django.contrib.auth import views as auth_views 에서 import views as auth_views 인 이유는, 우리가 기존에 app에 있던 views.py와 혼동을 주지 않기 위해서 다른 이름으로 불러오는 것이다.

 

두번째로는 password_reset_confirm/<uidb64>/<token>/ 인 부분인데, 이는 Django documentation을 보면 알 수 있다:

출처: <https://docs.djangoproject.com/en/3.1/topics/auth/default/#user-objects>

Documentation을 보면 <uidb64><token>을 url에 통과를 시켜줘야 한다고 명시되어 있다. <uidb64>의 경우, user id를 암호화 시켜주는 것이고, <token>은 이 아이디와 비밀번호가 일치하는지를 확인시켜주는 것이다. 

 

마지막으로, 이렇게 하고 views.py에 아무것도 추가하지 않아도 된다. 이유는 우리는 애초에 from django.contrib.auth import views as auth_views에서 불러온 함수이기 때문에, 이미 함수는 처리되었기 때문이다. (물론 조금더 customizing을 하고 싶을 경우 우리가 views.py에 새로 코드를 짜주어야 할 것이지만, 이 경우 우리는 Django를 간단하게 배우는데에 초점을 맞추고 있기 때문에 이 단계 까지는 가지 않겠다.)

 

 

※ Email SMTP 설정하기

보통 이렇게 비밀번호를 재설정 할 경우에는, 비밀번호를 재설정하기 위해 자신의 이메일 주소로 이메일이 전송되게끔 하고는 한다. 따라서 settings.py에 다음과 같이 설정해준다:

# settings.py
...
# SMTP Configuration
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'your_email@example.com'
EMAIL_HOST_PASSWORD = 'your_password'

이 tutorial의 경우, Gmail을 예시로 사용했다. 따라서 EMAIL_HOST'smtp.gmail.com'이 되는 것이고, EMAIL_PORT587, 587TLS 이기 때문에 True 값으로 입력해주게 되는 것이다. 자신이 사용할 이메일과 그 이메일의 비밀번호를 각자 알아서 넣어주면 될 것이다. (이 이메일과 비밀번호는 비밀번호를 재설정하고 싶은 상대에게 이메일을 보내게 해줄 이메일 주소를 입력해야 한다.)

 

이렇게 하는 방식은 좋으나, production level에서는 이메일 비밀번호와 SECRET_KEY라고 적힌 부분은 따로 json 파일을 만들어서 별도로 보관하여, 사용자들이 접근하지 못하게끔 하는 것이 좋을 것이다:

 

 

※ Overriding 기존 template

그렇다면 이제 reset_password에 들어가보자:

하지만 들어가면 이렇게 uglytemplate이 불러와진다. 이럴 경우에는 다음과 같이 urls.py를 바꿔주면 된다:

# urls.py

urlpatterns = [
    ...
    path('reset_password/', auth_views.PasswordResetView.as_view(template_name="accounts/reset_password"), name="reset_password"),
    path('pasword_reset_done/', auth_views.PasswordResetDoneView.as_view(template_name="accounts/password_reset_done.html"), name="password_reset_done"),
    path('password_reset_confirm/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(template_name="accounts/password_reset_confirm.html"), name="password_reset_confirm"),
    path('password_reset_complete/', auth_views.PasswordResetCompleteView.as_view(template_name="accounts/password_reset_complete.html"), name="password_reset_complete"),
    ...
	]

as_view() 사이에 template_name=""을 추가하고 templates/accounts/reset_password.html, password_reset_done.html, password_reset_confirm.html, password_reset_complete.html을 추가해준다. (url의 이름과 template의 이름은 편한대로 바꿔주면 된다.)

 

reset_password.html은 다음과 비슷해야할 것이다:

<!-- reset_password.html -->
<h3>Password reset</h3>

<p>Forgotten your password? Enter your email address below, and we’ll email instructions for setting a new one.</p>

<form method="post">

	{% csrf_token %}
	{{form}}
	<input type="Submit" name="Send email">
	
</form>

password_reset_done.html:

<!-- password_reset_done.html -->
<h3>Password reset sent</h3>


<p>We’ve emailed you instructions for setting your password, if an account exists with the email you entered. You should receive them shortly.</p>

<p>If you don’t receive an email, please make sure you’ve entered the address you registered with, and check your spam folder.</p>

password_reset_confirm.html:

<!-- password_reset_confirm.html -->
<h3>Enter new password</h3>

<p>Please enter your new password twice so we can verify you typed it in correctly.</p>

<form method="post">

	{% csrf_token %}
	{{form}}
	<input type="Submit" name="Update Password">
	
</form>

password_reset_complete.html:

<!-- password_reset_complete.html -->
<h3>Password reset complete</h3>

<p>Your password has been set. You may go ahead and log in now.</p>

<a href="/">Log in</a>

reset_password.html 과 password_reset_confirm.html 의 경우, 이메일을 제출하고, 새로운 비밀번호를 제출하는 form이 들어가있기 때문에 위와 같이 form을 넣어줘야 한다.

 

물론 이렇게 해주어도 다음과 같이 ugly하게 나타난다:

이는 csstemplate 수정을 통해 할 수 있을 것이다.

 

 

※ 추가로 (password_reset_confirm.html 수정하기)

위에 보여준대로 단순히 {{form}}password_reset_confirm.html에 통과시킬 경우, 다음과 같이 화면이 나타난다:

위와 같이 매우 ugly 하게 나타난다. 따라서 이를 조금이나마 원하는대로 바꾸려면 Django Github를 보면서 맞는 fieldlabel을 찾아서 하면 된다. 다음을 예시로 본다면:

<!-- password_reset_confirm.html -->
<h3>Enter new password</h3>

<p>Please enter your new password twice so we can verify you typed it in correctly.</p>

<form method="post">

	{% csrf_token %}
	{{form.new_password1.label}}
	{{form.new_password1}}
	<br>
	{{form.new_password2.label}}
	{{form.new_password2}}
	<input type="Submit" name="Update Password">
	
</form>

 

물론 이렇게 해도 ugly하게 나오는 것은 마찬가지이다. 하지만 Django GithubDjango Documentation을 적절하게 사용한다면 원하는 방식으로 수정할 수 있을 것이다.

 

 

이렇게 비밀번호 재설정하는 것을 이메일을 보내는 것을 통해 구현해냈다. 하지만 아직 이 사용자에 관한 다음 사항들을 설정하지 않았다:

  1. 아이디를 까먹었을 경우? → 이메일로 아이디를 보내게끔 함
  2. 비밀번호를 까먹었을 경우? → 아이디와 비밀번호를 입력하고 일치할 경우 새비밀번호/기존 비밀번호를 이메일로 보내줌

이 두가지는 다음 기회가 됐을 때 구현해보도록 하겠다.