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

<Django 공부하기> Forgot ID? 구현하기

category Django 공부하기 2020. 11. 10. 23:54

이전에는 PasswordResetView / PasswordResetDoneView / PasswordResetConfirmView / PasswordResetCompleteView 를 통해 간단하게 구현해냈다. 그렇다면 이번에는 만약 아이디를 까먹었을 때, 이메일로 아이디를 보내주는 것을 한번 구현해보도록 하겠다.

 

 

※ forgot_id.html 만들기 / urls.py 추가하기

우선, 로그인이 되어있지 않을때, 아이디를 까먹었다는 링크를 누르게 된면 해당 페이지로 이동하게끔 해줄 것이다.

Forgot ID?를 누른다면 다음과 같은 HTML 템플릿으로 이동한다.

<h3>Forgot ID</h3>

<p>Forgotten your ID? Enter your email address below, and we’ll email your ID.</p>

<form method="post">

	{% csrf_token %}
	Email: <input type="email" name="email">
	<input type="Submit" name="email_submit">

	{% for message in messages %}
		{{message}}
	{% endfor %}
	
</form>

여기에는 email을 넣을 수 있는 박스가 존재하고, input type="email로 해주어야 이메일을 받아들이는지 Django가 인식 할 수 있을 것이다. 아래의 message는 조금 있다가 설명하도록 하겠다.

 

다음은 urls.py에 다음과 같은 path를 추가해준다;

from django.urls import path
from . import views

urlpatterns = [
    ...
    path('forgot_id/', views.ForgotIDView, name="forgot_id"),
    ...
    ]

 

※ views.py 수정하기

이제는 ForgotIDView를 추가하여, 들어오려는 사용자가 form이 있는 이 페이지에 접근 했을 때, 그리고 이 페이지에서 데이터를 통과시킬 때 어떤 행동을 취해줄 것인지 views.py에 쓴다.

# views.py
from django.shortcuts import render, redirect
from django.conf import settings

from django.contrib import messages
from django.contrib.auth.models import User
from django.core.mail import EmailMessage

from .decorators import unauthenticated_user


@unauthenticated_user
def ForgotIDView(request):
	context = {}
	if request.method == 'POST':
		email = request.POST.get('email')
		try:
			user = User.objects.get(email=email)
			if user is not None:
				method_email = EmailMessage(
					'Your ID is in the email',
					str(user.username),
					settings.EMAIL_HOST_USER,
					[email],
					)
				method_email.send(fail_silently=False)
				return render(request, 'accounts/id_sent.html', context)
		except:	
			messages.info(request, "There is no username along with the email")
	context = {}
	return render(request, 'accounts/forgot_id.html', context)

 

  1. 우선 함수가 request.methodPOST인지 확인을 한다.
  2. 그리고 이 email이라는 변수에 request.POST.get('email')을 저장시켜준다.
  3. try라는 method를 통해 user라는 변수값에 User.objects.get(email=email)을 통해 POSTemail값을 가진 사용자를 불러온다.
  4. 만약 그러한 사용자가 없으면 except에 선언된 messages.info를 통해 해당 이메일을 가진 사용자는 없다는 것을 메세지로 출력해준다.
  5. 해당 이메일을 가진 사용자가 있을 경우, method_email에 EmailMessage를 저장시켜주는데, 이때 괄호 안에 있는 값들을 통과시킨다 (이 부분에 대해서는 밑에 설명하겠다.)
  6. 이후, 성공적으로 이메일이 보내졌으면, id_sent.html로 이동시킨다.

 

EmailMessage란 무엇인가?

우선 이 EmailMessage를 설명하기 위해서는 Sending Email이라는 Django Documentation을 봐야한다:

출처: <https://docs.djangoproject.com/en/3.1/topics/email/>

  • subject - 'Hello' 인 부분은 이메일의 제목이라고 생각하면 된다
  • body - 'Body goes here' 인 부분은 메일의 내용이라고 생각하면 된다. 이를 render_to_string을 사용하여 html template을 로딩하는 방법이 있다.
  • from_email - 'from@example.com'인 부분은 보내는 사람의 이메일이다. 우리는 settingsimport하여 settings.EMAIL_HOST_USER을 사용하여 settings.py에 써놓은 이메일을 불러와준다.
  • to - ['to1@example.com', 'to2@example.com']은 보내는 대상의 이메일들을 리스트로 넣는 것이다. 이번 포스팅의 경우 입력받은 이메일을 통과시켜주는 것이기 때문에 우리는 [email]로 대체하였다.
  • bcc - ['bcc@example.com']은 숨은 참조인데, 거의 사용할 일이 없으리라 생각된다.

마지막으로 method_email.send(fail_silently=False)를 통해, 이메일 보내면서 생기는 예외들은 무시처리 시켜주면서 이메일을 송신시켜주는 역할을 한다.

 

 

Email Template을 추가하기

아까 말한, views.pybodyrender_to_string을 사용하여 html template을 추가할 수 있다고 말했다. 이는 다음과 같이 views.py를 수정해주면 된다:

# views.py
...
from django.template.loader import render_to_string
...
def ForgotIDView(request):
	context = {}
	if request.method == 'POST':
		email = request.POST.get('email')
		try:
			user = User.objects.get(email=email)
			if user is not None:
				template = render_to_string('accounts/email_template.html', {'name': user.first_name, 'id':user.username})
				method_email = EmailMessage(
					'Your ID is in the email',
					template,
					settings.EMAIL_HOST_USER,
					[email],
					)
				method_email.send(fail_silently=False)
				return render(request, 'accounts/id_sent.html', context)
		except:
			messages.info(request, "There is no username along with the email")

render_to_string을 사용하여 accounts/email_template에 추가한 email_template.html을 통과시켜주고, 이 email_template 안에 있는 {{name}}{{id}} 가 각각 무엇을 지칭할 것인지 나타내주게끔 하면된다.

 

email_template.html은 다음과 비슷하게 생겼을 것이다 (매우 간략한 버젼이다):

hey {{name}}!

The following is your ID:
{{id}}

 

 

※ urls.py 에 id_sent.html을 추가하지 않았는데 어떻게 작동하는 것일까

지금 보면 위의 urls.pyid_sent.html에 관한 path를 추가하지 않았다. 그럼에도 불구하고 templates/accounts 폴더에 id_sent.html을 넣고, 이를 ForgotIDView에서 이메일을 보내고 return render 할 때 사용하는 것이 가능하다.

 

이유는 우리는 따로 이 id_sent.html을 접근하려고 할 것이 아니라, 단순히 이메일이 보내졌을 때만 접근하려고 하기 때문에 일반 사용자들이 접근을 하게끔 할 필요도 없을 뿐더러, 없어도 잘 작동하기 때문이다. 따라서 다로 주소창에 localhost:8000/id_sent/ 와 같이 입력한다면 오류가 날 것이다.

 

 

 

 

이렇게 아이디를 까먹었을 때, 사용자의 이메일에 메일을 보내는 방식으로 아이디를 확인하는 방법에 대해 알아보았다.