여태까지 특별한 프로젝트를 만들어 보지는 않았다. 이번에는 django를 통해 modeling을 해서 database를 연결시키고 view를 작성할 때 정규 표현식을 사용하여 회원가입의 기능을 구현해볼 것이다.
User(사용자)라는 테이블을 만들 것이며 그 안에 이름, 이메일, 비밀번호, 핸드폰 번호, 웹사이트, 별명, 주소, 소개에 해당하는 column을 생성할 것이다. 간단한 구조의 테이블이지만 생각해 봐야 할 부분은 각 column의 filed 속성들이다.
#models.py
from django.db import models
class User(models.Model):
name = models.CharField(max_length=45)
email = models.CharField(max_length=200)
password = models.CharField(max_length=45)
phone_number = models.CharField(max_length=45, null=True)
web_site = models.CharField(max_length=200, null=True)
nick_name = models.CharField(max_length=45, null=True)
address = models.CharField(max_length=200, null=True)
introduce = models.TextField(null=True, default='')
class Meta:
db_table = 'users'
import models에서 대부분의 field와 method들을 제공받기에 따로 field를 import 하지 않아도 된다. model을 보면 속성 내부에 꼭 필요한 필수 정보를 제외한 나머지는 null=True를 지정해 줬다. introduce를 제외한 대부분은 CharField 속성을 사용하였는데 넉넉한 길이를 지정해 줬다. 핸드폰 번호의 경우 InterField로 지정하게 되면 숫자 '0'으로 시작하게 될 때 오류가 발생할 수도 있으니 주의해야 한다.
modeling을 끝냈으면 회원가입 기능을 구현하기 위해 view를 작성할 것이다. 일반적으로 회원가입을 할 경우 필수 항목이 비어있을 경우 오류가 발생하고 사용자의 고유의 id 값을 중복 검사를 하며, 형식에 맞는 비밀번호와 id 값을 입력해야 한다. 이런 기능을 view에서 작성할 것이며, email과 password는 정규 표현식을 사용하여, 형식에 맞게 입력되었는지 확인하는 기능을 구현해볼 것이다.
물론 파이썬 문법을 사용하여 상위에 언급한 것처럼 형식에 맞는 확인하는 email과 password를 확인할 수 있다. 그러나 코드의 길이가 길어지게 된다. 우리는 항상 짧고 간결한 코드를 원하기 때문에 정규 표현식을 사용할 것이다.
파이썬에서는 정규 표현식 모듈 re를 지원하므로 import 해와서 정해진 형식에 맞는 확인하겠다.
import re
Email = re.compile("^[a-zA-Z0-9+-_.]+@[a-zA-z0-9-]+\.[a-zA-z0-9-]+$")
PW = re.compile("/^(?=.*[a-zA-Z])((?=.*\d)|(?=.*\W)).{8,20}$/")
if PW.match(data['password']) is None or Email.match(data['email']) is None:
return JsonResponse({'message':' INVALID_FORMAT'}, status=400)
필자는 정제할 정규 표현식을 변수에 저장하여 요청받은 데이터를 match 함수를 사용하여 일치하는지 확인하였고 불일치할 경우에는 None을 반환하여 400에러를 response 하게 하였다.
views.py
from django.http.response import JsonResponse
from django.views import View
import json
from users.models import User
import re
class UserView(View):
def post(self, request):
try:
data = json.loads(request.body)
Email = re.compile("^[a-zA-Z0-9+-_.]+@[a-zA-z0-9-]+\.[a-zA-z0-9-]+$")
PW = re.compile("/^(?=.*[a-zA-Z])((?=.*\d)|(?=.*\W)).{8,20}$/")
if PW.match(data['password']) is None or Email.match(data['email']) is None:
return JsonResponse({'message':' INVALID_FORMAT'}, status=400)
if User.objects.filter(email = data["email"]).exists():
return JsonResponse({"message": "OVERLAP"}, status=400)
User.objects.create(
name = data['name'],
email = data['email'],
password = data['password'],
phone_numbers = data['phone_numbers'],
web_site = data['website'],
nick_name = data['nick_name'],
address = data['address'],
introduce = data['introduce']
)
return JsonResponse({'message': "SUCCESS"}, status=201)
except KeyError:
return JsonResponse({"message": "KEY_ERROR"}, status=400)
전체적으로 try except 구문을 사용하여, 필수 column의 값이 요청되지 않았을 경우 key error를 반환한다. 중복검사를 위해 쿼리 filter 함수를 사용하여 불러오고 exists()를 사용하여 True일 경우 에러를 발생하며, 상위 조건문에 해당되지 않는다면 201상태를 반환하여 회원가입을 시켜준다.
기존의 만들어져 있는 모델과 데이터를 이용해서 로그인 기능을 간단하게 구현해볼것이다. 굳이 모델을 손볼 필요 없이 views.py에 새로운 로그인 클래스를 생성한다.
views.py
class LoginView(View):
def post(self, request):
try:
data = json.loads(request.body)
if not User.objects.filter(email=data['email']).exists():
return JsonResponse({"message": "INVALID_USER"}, status=401)
if User.objects.get(email=data['email']).password != data['password']:
return JsonResponse({"message": "INVALID_USER"}, status=401)
return JsonResponse({'message': "SUCCESS"}, status=200)
except KeyError:
return JsonResponse({"message": "KEY_ERROR"}, status=400)
전체적으로 회원가입과 비슷하게 try~except 구문을 사용하였다. 필수 요청 값이 body에 빠져서 올 경우 keyerror를 발생시킨다. 첫 번째 조건문에 exists() 함수를 사용하여 요청된 사용자의 email이 존재하는지 확인하고 존재하지 않을 경우 에러를 response 한다. 두 번째 조건문에는 데이터 베이스의 email의 password가 요청된 사용자의 비밀번호가 일치하는지 확인하고 불일치할 경우 에러를 response 한다. 상위 조건문에 걸리지 않고 내려올 경우 SUCCESS라는 문구와 함께 로그인이 됐다는 메시지를 response 한다. 이때 status는 201이 아니라 200을 반환한다. 201은 POST 나 PUT으로 게시물 작성이나 회원 가입 등의 새로운 데이터를 서버에 생성하는 작업이 성공했을 때 사용되며 login 상태에서는 가장 일반적으로 볼 수 있는 HTTP 상태인 200을 사용한다.