회원가입, 로그인, 댓글 작성 기능을 하는 엔드포인트를 구현하고 httpie로 회원가입, 로그인 테스트를 진행했다. 기능을 기반으로 앱을 분리해서 작업했기 때문에 회원가입, 로그인이 이루어질 users 앱을 생성하고, 댓글 작성 및 확인이 이루어질 comments 앱을 생성했다.
회원가입과 로그인 (user앱에서 진행)
먼저 models.py에서 데이터 저장에 앞서 필요한 데이터 테이블 틀을 잡았다.
from django.db import models
class Users(models.Model):
# 가입 시 아이디(username)와 비밀번호(password) 정보를 받아야 하므로
# user_data 테이블에 username열과 password열을 만들어줌
username = models.CharField(max_length=50)
password = models.CharField(max_length=300)
class Meta:
db_table = 'user_data'
그 다음 views.py에서 사용자가 회원가입 페이지와 로그인 페이지로 들어왔을 때 어떤 화면을 보여줄지 설정해준다.
import json
from django.views import View
from django.http import JsonResponse, HttpResponse
from .models import Users
# /users/로 들어왔을 때 출력되는 화면
class MainView(View):
def get(self, request):
return JsonResponse({'Welcome to':'Westagram', 'Sign-up':'/users/sign-up', 'Log-in':'/users/log-in'}, status=200)
# /users/sign-up/에서 액션에 따라 띄워줄 화면 설정
class SignUpView(View):
# 데이터를 입력하는 것이므로 get이 아닌 post 메서드를 사용한다.
def post(self, request):
data = json.loads(request.body)
# 유저가 입력한 데이터인 data['username']과 data['password']이
# 각각 username과 password 열에 저장된다.
try:
Users(
username = data['username'],
password = data['password']
).save()
# 에러가 발생하면 401코드와 함께 지정한 메시지를 띄운다.
except:
return JsonResponse({'message':'INVALID_ID'}, status=401)
# 에러가 발생하지 않고 잘 작동하면 200코드와 함께 지정한 메시지를 띄운다.
else:
return JsonReponse({'message':'WELCOME'}, status=200)
# /users/sign-up/을 호출했을 때 출력되는 화면
def get(self, request):
return JsonResponse({'Please':'Sign-up'}, status=200)
# /users/log-in/에서 액션에 따라 띄워줄 화면 설정
class LogInView(View):
# 데이터를 입력하는 것이므로 get이 아닌 post 메서드를 사용한다.
def post(self, request):
data = json.loads(request.body)
# sign-up과는 달리 데이터를 신규로 입력하는 것이 아니므로 .save()는 쓰지 않는다.
Users(
username = data['username'],
password = data['password']
)
# 아이디가 유효하면 비밀번호가 유효한지 검사하고,
# 아이디나 비밀번호가 유효하지 않다면 401코드와 함께 지정한 메시지를 띄운다.
# 아이디와 비밀번호가 모두 일치한다면 200코드와 함께 지정한 메시지를 띄운다.
try:
if Users.objects.filter(username=data['username']).exists():
user_id = Users.objects.get(username=data['username'])
if data['password'] == user_id.password:
return JsonResponse({'message':'WELCOME, ' + data['username']}, status=200)
else:
return JsonResponse({'message':'비밀번호가 틀립니다.'}, status=401)
else:
return JsonResponse({'message':'아이디가 없습니다.'}, status=401)
except:
return JsonResponse({'message':'INVALID_USER'}, status=401)
# 로그인 정보를 받아서 입력한 유저의 정보만을 호출하고 싶었으나 아래처럼 하면 에러 발생
def get(self, request):
login_data = Users.objects.filter(username=data['username']).values()
return JsonResponse({'user':list(login_data)}, status=200)
위에서 화면 별 액션을 설정해주었으므로 유저가 접속한 url과 views.py 파일을 연결해준다. 앱 디렉토리 안에는 urls.py가 없으므로 새로 만들어서 내용을 입력해준다.
from django.urls import path
from .views import MainView, SignUpView, LogInView
urlpatterns = [
# /users/ 페이지에서는 MainView를 띄워준다.
path('', MainView.as_view()),
# /users/sign-up/ 페이지에서는 SignUpView를 띄워준다.
path('sign-up/', SignUpView.as_view()),
# /users/log-in/ 페이지에서는 LogInView를 띄워준다.
path('log-in/', LogInView.as_view()),
]
/users/ 페이지와 /comments/ 페이지 호출이 왔을 경우 해당 페이지로 넘어갈 수 있도록 메인 디렉토리의 urls.py에서 연결해준다.
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('users/', include('users.urls')),
path('comments/', include('comments.urls')),
]
회원가입 테스트
데이터 입력(=회원가입)은 python shell과 sqlite3에서 진행했고, 테스트는 httpie로 진행했다.
# username과 password 입력하기 (가입)
>>> Users.objects.create(username='test1', password='test1234')
# 출력값(객체 생성)
<Users: Users object (1)>
sqlite에서 테이블에 잘 들어갔나 확인을 해보자.
select * from user_data;
# 출력값
id username password
---------- ---------- ----------
1 test1 test1234
같은 아이디로 가입을 시도하면 401코드 에러가 떠야한다. 이미 가입했던 test1 아이디로 가입 시도를 해보겠다.
http -v http://127.0.0.1:8001/users/sign-up/ username=test1 password=test1234
그럼 아래와 같은 결과값을 출력한다.
# request 메시지의 start line
POST /users/sign-up/ HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 45
Content-Type: application/json
Host: 127.0.0.1:8001
User-Agent: HTTPie/2.1.0
{
"password": "test1234",
"username": "test1"
}
# response 메시지의 start line
# 가입에 실패했으므로 에러코드 401 리턴
HTTP/1.1 401 Unauthorized
Content-Length: 25
Content-Type: application/json
Date: Sun, 14 Jun 2020 12:07:21 GMT
Server: WSGIServer/0.2 CPython/3.8.3
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
# 에러코드 401과 리턴하기로 설정한 메시지
{
"message": "INVALID_ID"
}
로그인 테스트
테스트는 터미널 상에서 httpie로 진행했다.
http -v http://127.0.0.1:8001/users/log-in/ username=test1 password=test1234
# request 메시지의 start line
POST /users/log-in/ HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 45
Content-Type: application/json
Host: 127.0.0.1:8001
User-Agent: HTTPie/2.1.0
{
"password": "test1234",
"username": "test1"
}
# response 메시지의 start line
# 로그인에 성공했으므로 200 코드 리턴
HTTP/1.1 200 OK
Content-Length: 29
Content-Type: application/json
Date: Sun, 14 Jun 2020 12:10:59 GMT
Server: WSGIServer/0.2 CPython/3.8.3
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
# 200 코드와 함께 리턴하기로 설정한 메시지
{
"message": "WELCOME, test1"
}
아이디나 비밀번호가 틀릴 때도 테스트 해보았다.
http -v http://127.0.0.1:8001/users/log-in/ username=test1 password=test123
# request 메시지의 start line
POST /users/log-in/ HTTP/1.1
# request 메시지의 headers
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 44
Content-Type: application/json
Host: 127.0.0.1:8001
User-Agent: HTTPie/2.1.0
# request 메시지의 body
{
"password": "test123",
"username": "test1"
}
# response 메시지의 start line
# 로그인에 실패했으므로 에러코드 401 리턴
HTTP/1.1 401 Unauthorized
# response 메시지의 headers
Content-Length: 27
Content-Type: application/json
Date: Sun, 14 Jun 2020 12:19:01 GMT
Server: WSGIServer/0.2 CPython/3.8.3
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
# response 메시지의 body
# 에러코드 401과 리턴하기로 설정한 메시지
{
"message": "INVALID_USER"
}
코멘트 기능 실습 내용은 다음 글에 이어서 기록하겠다.