Django - ExcelCalCulator_2

Page content

개요

  • Django 한 그릇 뚝딱 교재의 내용에서 멀티캠퍼스 강의에 맞게 일부 수정함
  • 2019년 버전이고 현재는 2023년이기 때문에 소스코드 변경 사항이 필요할 거 같아서 글을 남김

교재 홍보

Untitled

Step 01 - 이전 글

Step 02 - 이메일 인증으로 회원 가입

  • 절차는 다음과 같다.
    • 회원 가입 화면에서 개인정보 입력 후 회원 가입하기 버튼 클릭 때 해당 정보로 유저 데이터 생성 및 DB에 저장, 이 때 인증되지 않은 유저로 등록
    • DB에 저장 후, 입력한 이메일로 인증 코드 발송
    • 발송된 인증 코드는 유저 이름과 함께 쿠키로 저장 후 인증 코드 입력 화면으로 전환
    • 인증 코드 입력 화면에서 인증 코드 입력 후 인증하기 버튼 클릭 때 입력된 코드와 쿠키에 저장된 인증 코드 비교 후 회원 성공/실패 처리
    • 성공 때는 회원의 인증 값을 true 로 설정, 실패 때 해당 회원정보 삭제

Step 03 - DB 설정

  • 사용자 정보를 저장할 수 있는 모델을 만들어야 한다.
  • 회원 가입 시 필요한 기본 정보 : 이름, 이메일, 비밀번호, 그리고 사용자의 인증여부를 체크해 주는 정보를 가지게 된다.
    • 파일 경로 : ExcelCalculate > main > models.py
from django.db import models

# Create your models here.
class User(models.Model):
    user_name = models.CharField(max_length = 20)
    user_email = models.EmailField(unique=True)
    user_password = models.CharField(max_length=100)
    user_validate = models.BooleanField(default=False)
  • User 모델을 정의했다면, 이를 반영하기 위해서 아래 명령어들을 통해 migrations 파일을 만들고 migrate 한다.
$ python manage.py makemigrations
Migrations for 'main':
  main\migrations\0001_initial.py
    - Create model User
$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, main, sessions
Running migrations:
  Applying main.0001_initial... OK

Step 04 - 회원가입 url 설정

  • 회원 가입 때 사용자 데이터를 저장하기 위해, 먼저 signup.html 에서 회원 가입 버튼 클릭 때 이동할 url 설정을 하도록 한다.

    • 파일 경로 : ExcelCalculate > main > templates > main > signup.html
    • 기존
    <h1> 회원가입 하기 </h1><br>
    <form action="" method="POST" id="signup-form">{% csrf_token %}
        <div class="input-group">
    
    • 수정
      • form 태그의 action값을 설정한다.
      • 사용자가 이름과 이메일, 비밀번호를 입력 후, 회원 가입 버튼을 누르면, ~/signup/join 과 같은 url 로 이동한다.
    <h1> 회원가입 하기 </h1><br>
    <form action="signup/join" method="POST" id="signup-form">{% csrf_token %}
        <div class="input-group">
    
  • main app 폴더의 urls.py 에 해당 url 처리를 추가한다.

    • 파일 경로 : ExcelCalculate > main > urls.py
    • 기존
    from django.urls import path 
    from . import views 
    
    urlpatterns = [
        path('', views.index, name="main_index"), 
        path('signup', views.signup, name="main_signup"), 
        path('signin', views.signin, name="main_signin"),
        path('verifyCode', views.verifyCode, name="main_verifyCode"),
        path('verify', views.verify, name="main_verify"), 
        path('result', views.result, name="main_result"), 
    ]
    
    • 수정
      • path('signup/join', views.join, name="main_join") 코드를 추가했다.
    from django.urls import path 
    from . import views 
    
    urlpatterns = [
        path('', views.index, name="main_index"), 
        path('signup', views.signup, name="main_signup"), 
        path('signup/join', views.join, name="main_join"), 
        path('signin', views.signin, name="main_signin"),
        path('verifyCode', views.verifyCode, name="main_verifyCode"),
        path('verify', views.verify, name="main_verify"), 
        path('result', views.result, name="main_result"), 
    ]
    

Step 05 - views.py 설정

  • views.py join 함수로 전달한다.

    • 파일 경로 : ExcelCalculate > main > views.py
    • 기존
    from django.shortcuts import render, redirect
    
    # Create your views here.
    def index(request):
        return render(request, 'main/index.html')
    
    def signup(request):
        return render(request, 'main/signup.html')
    
    def signin(request):
        return render(request, 'main/signin.html')
    
    def verifyCode(request):
        return render(request, 'main/verifyCode.html')
    
    def verify(request):
        return redirect('main_index')
    
    def result(request):
        return render(request, 'main/result.html')
    
    • 수정
      • join 함수를 추가하였다.
        • 일단 redirect 함수를 통해 인증 코드 입력 화면으로 가도록 한다.
        • 함수 내부에 사용자가 입력한 값들을 받아서 DB에 저장한다.
        • 동시에 인종 코드 생성 후 사용자의 이메일로 인증 코드를 보내준다.
    from django.shortcuts import render, redirect
    
    # Create your views here.
    def index(request):
        return render(request, 'main/index.html')
    
    def signup(request):
        return render(request, 'main/signup.html')
    
    def join(request):
        print(request)
        name = request.POST['signupName']
        email = request.POST['signupEmail']
        pw = request.POST['signupPW']
        user = User(user_name = name, user_email = email, user_password = pw)
        user.save()
    
        return redirect('main_verifyCode')
    
    def signin(request):
        return render(request, 'main/signin.html')
    
    def verifyCode(request):
        return render(request, 'main/verifyCode.html')
    
    def verify(request):
        return redirect('main_index')
    
    def result(request):
        return render(request, 'main/result.html')
    

Step 06 - admin.py 설정

  • views.py join 함수로 전달한다.

  • 실제 회원 가입 화면에서 알맞은 정보를 입력한 후에 회원 가입 버튼을 누를 시, 실제로 데이터가 잘 저장되었는지 확인하기 위해 admin 페이지를 이용한다.

  • User 모델에 대해서는 admin 페이지에 등록하지 않았기 때문에 모델에 대한 등록을 먼저 진행한다.

    • 파일 경로 : ExcelCalculate > main > admin.py
    from django.contrib import admin
    from .models import *
    
    # Register your models here.
    admin.site.register(User)
    
  • python runserver를 실행 한 후, superuser로 로그인 하면 아래와 같이 Users라는 이름으로 등록된 것을 확인한다.

Untitled

Step 07 - 인증코드 생성

  • 4자리 인증 코드는 각 시점에 따라 랜덤하게 생성된다.

  • 해당 인증 코드를 이메일로 발송하기 전, 인증 여부를 체크하기 위해 웹 쿠키에 저장한다.

    • views.py 에서 join 함수를 업데이트 한다.
    • 기존
    from django.shortcuts import render, redirect
    
    def join(request):
        print(request)
        name = request.POST['signupName']
        email = request.POST['signupEmail']
        pw = request.POST['signupPW']
        user = User(user_name = name, user_email = email, user_password = pw)
        user.save()
        return redirect('main_verifyCode')
    
    • 수정
      • code = randint(1000, 9000) : 1000부터 9999 사이의 숫자를 랜덤하게 생성
      • response.set_cookie('code', code) : 생성한 4자리 랜덤 숫자를 설정
      • 추후 인증 코드를 확인한 후에 어떤 유저의 인증을 진행하는지 알기 위해 user의 id값을 쿠키로 저장해준 뒤 해당 response를 사용자에게 반환
      • 생성한 인증 코드를 사용자가 입력한 이메일로 발송해주어야 한다.
    from django.shortcuts import render, redirect
    from random import * 
    from .models import *
    
    def join(request):
        print(request)
        name = request.POST['signupName']
        email = request.POST['signupEmail']
        pw = request.POST['signupPW']
        user = User(user_name = name, user_email = email, user_password = pw)
        user.save()
        code = randint(1000, 9000)
        response = redirect('main_verifyCode')
        response.set_cookie('code', code)
        response.set_cookie('user_id', user.id)
    
        # call send
        return response
    

Step 08 - 이메일 발송 기능

  • 4자리 인증 코드는 각 시점에 따라 랜덤하게 생성된다.
  • sendEmail app에서 send 라는 이름의 함수로 만들 것.
  • join 함수에서는 해당 send 함수를 호출하며 사용자의 이메일과 4자리 랜덤 코드를 매개 변수로 전달만 해줄 것

check 1 - email_format.html 파일 작성

  • html 파일로 된 메일 포맷을 만들어 sendEmail apptemplates 안에 넣어 준다.
  • 파일 경로 : ExcelCalculate > sendEmail > templates > sendEmail > email_format.html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <h1>ExcelCalculate 회원 가입</h1>
        <p>다음의 인증 코드를 입력해 주세요</p>

        <h2> {{ verifyCode }} </h2>
    </body>
</html>

check 2 - views.py 에서 send 함수 수정

  • 기존에 작성 된 send 함수를 수정한다.

    • 파일 경로 : ExcelCalculate > sendEmail > views.py
    • 기존
    from django.shortcuts import render
    from django.http import HttpResponse
    
    # Create your views here.
    def send(receiverEmail, verifyCode):
        return HttpResponse("sendEmail, send function!")
    
    • 수정
    from django.shortcuts import render
    from django.http import HttpResponse
    from django.core.mail import send_mail, EmailMessage
    from django.template.loader import render_to_string
    
    # Create your views here.
    def send(receiverEmail, verifyCode):
        try:
            content = {'verifyCode' : verifyCode}
            msg_html = render_to_string('sendEmail/email_format.html', content)
            msg = EmailMessage(subject="인증 코드 발송 메일", 
                               body=msg_html, 
                               from_email="jhjung@dschloe.com", 
                               bcc=[receiverEmail])
            msg.content_subtype="html"
            msg.send()
            return True
        except:
            return False
    
  • 그동안 views.py 파일에 작성했던 함수들은 기본적으로 request 를 인자로 받는다. 그러나 send 함수에서는 request 를 인자로 받지 않고, 단지 수신자 이메일과 인증 코드만 인자로 받는다.

    • 기존에는 GET 또는 POST 방식으로 넘어오기 때문에 request 를 통해 받아서 사용하기 때문에 request 를 사용한다.
    • 그런데, 여기에서는 join 함수에서 메일을 보내려고 호출하는 함수일 뿐이다.
    • 따라서, 반환값도 간단하게 정상적으로 메일이 발송되면 True, 그렇지 않으면 False를 반환하도록 한다.

check 3 - SMTP 서버

  • 메일 발송 함수를 구현했다면, 다음과 같이 세팅을 진행한다.

    • 파일 경로 : ExcelCalculate> ExcelCalculate > settings.py
    ALLOWED_HOSTS = []
    
    # Email Settings
    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
    EMAIL_HOST = 'smtp.gmail.com'
    EMAIL_USE_TLS = True
    EMAIL_PORT = 587
    EMAIL_HOST_USER = 'your@email.com'
    EMAIL_HOST_PASSWORD = 'yourpassword'
    
  • EMAIL_HOST_PASSWORD는 아래 그림에서 2단계 인증을 클릭한다.

Untitled

  • 앱 비밀번호를 확인한다.

Untitled

Untitled

  • 생성 버튼을 클릭하면 16자리의 비밀번호가 등장한다. 이 부분을 붙여 넣는다.

check 4 - sendEmail send 함수 수정 추가

  • 앞서 주석 처리했던 이메일 발송 함수 호출 영역을 다시 수정하도록 한다.

  • 파일 경로 : ExcelCalculate > main > views.py

    • 기존
    from django.shortcuts import render, redirect
    from random import * 
    from .models import *
    
    def join(request):
        print(request)
        name = request.POST['signupName']
        email = request.POST['signupEmail']
        pw = request.POST['signupPW']
        user = User(user_name = name, user_email = email, user_password = pw)
        user.save()
        code = randint(1000, 9000)
        response = redirect('main_verifyCode')
        response.set_cookie('code', code)
        response.set_cookie('user_id', user.id)
    
        # 이메일 발송 함수 호출
        return response
    
    • 수정
    from django.shortcuts import render, redirect
    from random import * 
    from .models import *
    from sendEmail.views import *
    
    def join(request):
        print(request)
        name = request.POST['signupName']
        email = request.POST['signupEmail']
        pw = request.POST['signupPW']
        user = User(user_name = name, user_email = email, user_password = pw)
        user.save()
        code = randint(1000, 9000)
        response = redirect('main_verifyCode')
        response.set_cookie('code', code)
        response.set_cookie('user_id', user.id)
    
        # 이메일 발송 함수 호출
        send_result = send(email, code)
        if send_result:
            return response
        else:
            return HttpResponse("이메일 발송에 실패했습니다!")
    

Step 09 - 인증코드 발송 메일 확인

  • 서버를 실행 후, 회원가입을 진행한다.

Untitled

  • 이제 다시 코드를 실행한 후, 회원가입을 진행해본다.

Untitled

  • 각 개인 메일에서 확인 해본다.

Untitled