티스토리 뷰

study/Django

Django - 회원가입 구현

xoxowo 2022. 7. 10. 21:31

회원가입 구현 

 

이전에 models.py에 클래스를 정의하여 데이터를 담을 수 있는 테이블을 만들었다면 HTTP통신을 통해 서버에 요청을 보내고 그 요청을 분석하여 처리할 수 있는 로직(View)을 실행시켜 데이터베이스와 통신하여 작업을 수행하고 요청에 맞는 응답을 보낼 수 있는 간단한 회원가입 API를 구현해보았다. 

 

HTTP를 통해 서버에 요청을 하면 전달하는 내용에 따라 내가 views.py에 정의한 오류들을 볼 수 있었고, 내가 정의하지 않은 오류가 발생할 경우 500 코드가 반환되는 것을... 볼 수 있었다.ㅠㅜ 아래 정의한 상태 코드 이 외 코드는 여기서 확인할 수 있다.

 

models.py

모델링 조건

→ 이름, 이메일, 비밀번호, 연락처 정보를 클라이언트에게서 받음

→ 이메일 로그인 방식을 사용하기 위해 회원가입 시 입력받은 이메일은 unique 속성 부여하여 중복 저장 방지

→ 비밀번호는 추후 암호화 작업을 하기 위해 max_length 길이를 200자로 변경

→ 데이터 이력 관리를 위해 created_at, updated_at column 추가

# users/models.py

from django.db import models

class StoreUser(models.Model) :
    name         = models.CharField(max_length = 20)
    email        = models.EmailField(max_length = 50, unique = True)
    password     = models.CharField(max_length = 200)
    phone_number = models.CharField(max_length = 50)
    created_at   = models.DateTimeField(auto_now_add = True)
    updated_at   = models.DateTimeField(auto_now = True)
    
    class Meta :
        db_table = 'stores_users'

 

views.py

HTTP 통신으로 받은 method 종류에 따라 수행하는 방법을 정의해야 하는데, 회원가입은 클라이언트가 정보를 실어 보내기 때문에 post method로 SignUpView클래스의 함수를 post 정의했다.

 

회원가입 조건

→ 이메일과 비밀번호는 파이썬 정규표현식을 만족해야 하며, 아닐 시 400 에러 반환

→ 로그인 시 이메일을 사용하기 때문에 이메일 중복 시에도 400 에러 반환 

→ 이메일과 패스워드가 전달되지 않을 경우 key error 반환

→ 회원가입 성공 시 201 반환

# users/views.py

import json, re <-이렇게 줄여 사용할 수 있으며 re는 정규표현식을 사용하기 위해 import함
import re

from unittest     import result
from django.http  import JsonResponse
from django.views import View
from users.models import StoreUser

class SignUpView(View):
    def post(self, request):
        data = json.loads(request.body) 
        email_form = re.compile('^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
        password_form = re.compile('^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{8,}$')

        try :
            if data['password'] and data['email'] == None :
                return JsonResponse({"message": "Email or Password is Empyt"}, status = 400)   

            if StoreUser.objects.filter(email=data['email']).exists():
                return JsonResponse({"message": "Already registered Email"}, status = 400)   

            if not email_form.match(data['email']) :
                return JsonResponse({"message": "Invalid email format"}, status = 400)   

            if not password_form.match(data['password']):
                return JsonResponse({"message": "Invalid password format"}, status = 400)
            
            StoreUser.objects.create(
                name         = data['name'],
                email        = data['email'],
                password     = data['password'],
                phone_number = data['phone_number'],
            )
            return JsonResponse({"message": "SUCCESS"}, status = 201)
            
        except KeyError :
            return JsonResponse({"message": "KEY_ERROR"}, status = 400)

 

사실 아직 try except 문에 익숙하지 않기 때문에 위 코드를 작성하기까지 많은 시간이 걸렸다.... (매우..)

내부를 살펴보면,

	try :
 		# 클라이언트가 전달해준 password값과 email 값이 없다면 400 반환
            if data['password'] and data['email'] == None :
                return JsonResponse({"message": "Email or Password is Empyt"}, status = 400)   
 	 # StoreUser 테이블에 필터를 걸어 저장되어있는 이메일과 일치하는 이메일이면  400 반환
         # .exists() 메서드는 단순히 존재하는지만 확인하기 때문에 filter와 자주 사용
            if StoreUser.objects.filter(email=data['email']).exists():
                return JsonResponse({"message": "Already registered Email"}, status = 400)   
	# 클라이언트가 준 이메일 형식이 정규표현식과 매치되지 않으면 400 반환 .match <-파이썬 정규표현식 함수
            if not email_form.match(data['email']) :
                return JsonResponse({"message": "Invalid email format"}, status = 400)   
	# 클라이언트가 준 패스워드 형식이 정규표현식과 매치되지 않으면 400 반환
            if not password_form.match(data['password']):
                return JsonResponse({"message": "Invalid password format"}, status = 400)
            
        # 위 if문들을 통과하면 StoreUser 테이블에 아래 형식대로 결과 값들을 저장 후 sussess /201 반환
            StoreUser.objects.create(
                name         = data['name'],
                email        = data['email'],
                password     = data['password'],
                phone_number = data['phone_number'],
            )
            return JsonResponse({"message": "SUCCESS"}, status = 201)
        # email, password는 키값인데 이 키값이 오타 또는 전해지지 않았다면 key error 400 반환
        except KeyError :
            return JsonResponse({"message": "KEY_ERROR"}, status = 400)

모든 조건을 만족 시

→ 회원가입 성공으로 201 코드 반환

http -v post 127.0.0.1:8000/users/signup name='카레' email='w@naver.com'  password='000000a!00'  phone_number=0001
POST /users/signup HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 98
Content-Type: application/json
Host: 127.0.0.1:8000
User-Agent: HTTPie/3.2.1
{
    "email": "w@naver.com",
    "name": "카레",
    "password": "000000a!00",
    "phone_number": "0001"
}
HTTP/1.1 201 Created
Content-Length: 22
Content-Type: application/json
Cross-Origin-Opener-Policy: same-origin
Date: Sun, 10 Jul 2022 11:45:09 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.8.13
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
    "message": "SUCCESS"
}

KEY ERROR 발생 시

→ http 서버 요청에 key값 오류 시  key error 400 코드 반환

http -v post 127.0.0.1:8000/users/signup name='카레' email=  passworㅑd=  phone_number=0001
POST /users/signup HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 83
Content-Type: application/json
Host: 127.0.0.1:8000
User-Agent: HTTPie/3.2.1
{
    "email": "",
    "name": "카레",
    "passworㅑd": "",
    "phone_number": "0001"
}
HTTP/1.1 400 Bad Request
Content-Length: 24
Content-Type: application/json
Cross-Origin-Opener-Policy: same-origin
Date: Sun, 10 Jul 2022 11:25:07 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.8.13
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "message": "KEY_ERROR"
}

중복된 이메일로 가입 시도 시

→ 이메일이 중복된 것을 확인 후 400 코드 반환

http -v post 127.0.0.1:8000/users/signup name='카레' email='a@naver.com' password='12347u!' phone_number=0001
POST /users/signup HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 95
Content-Type: application/json
Host: 127.0.0.1:8000
User-Agent: HTTPie/3.2.1
{
    "email": "a@naver.com",
    "name": "카레",
    "password": "12347u!",
    "phone_number": "0001"
}
HTTP/1.1 400 Bad Request
Content-Length: 39
Content-Type: application/json
Cross-Origin-Opener-Policy: same-origin
Date: Sun, 10 Jul 2022 11:17:34 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.8.13
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
    "message": "Already registered Email"
}

비밀번호가 정규표현식 조건을 만족시키지 못한 경우

비밀번호 포멧이 유효하지 않아 400 코드 반환

http -v post 127.0.0.1:8000/users/signup name='카레' email='w@naver.com'  password='00000000'  phone_number=0001
POST /users/signup HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 96
Content-Type: application/json
Host: 127.0.0.1:8000
User-Agent: HTTPie/3.2.1
{
    "email": "w@naver.com",
    "name": "카레",
    "password": "00000000",
    "phone_number": "0001"
}
HTTP/1.1 400 Bad Request
Content-Length: 38
Content-Type: application/json
Cross-Origin-Opener-Policy: same-origin
Date: Sun, 10 Jul 2022 11:42:25 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.8.13
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
    "message": "Invalid password format"
}

이메일이 정규표현식 조건을 만족시키지 못한 경우

→ 이메일 포멧이 유효하지 않아 400 코드 반환

http -v post 127.0.0.1:8000/users/signup name='카레' email='w2.com'  password=''  phone_number=0001
POST /users/signup HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 83
Content-Type: application/json
Host: 127.0.0.1:8000
User-Agent: HTTPie/3.2.1
{
    "email": "w2.com",
    "name": "카레",
    "password": "",
    "phone_number": "0001"
}
HTTP/1.1 400 Bad Request
Content-Length: 35
Content-Type: application/json
Cross-Origin-Opener-Policy: same-origin
Date: Sun, 10 Jul 2022 11:29:11 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.8.13
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
    "message": "Invalid email format"
}

 


내용 전문 및 출처 - mozila

'study > Django' 카테고리의 다른 글

Django - 암호화 (bcrypy)  (0) 2022.07.12
Django - 회원 로그인 구현  (0) 2022.07.10
Django - QuerySet 다루기 (초보)  (0) 2022.07.09
Django - MtoM Field 없이 구현  (0) 2022.07.06
westarbucks 만들기 - models.py  (0) 2022.07.05
댓글