바로 직전에 이어서 Login과 Comment 기능을 수정하고자 한다. 멘토님의 조언을 받아 해당 api를 만드는데 있어 아래와 같은 기준을 적용하고자 한다.
views.py
에는 SignInView
, SignUpView
를 구현하여 간단히 가입 기능도 추가하여 테스트App 설계를 새로 하게 되어서 project 내의 app을 먼저 정리했다. 그리고 account와 comment 앱을 새로 생성했다.
또한 git이 설정된 프로젝트이고 app 구조를 전체적으로 수정하여 아래와 같은 과정을 거친 뒤 account와 comment 앱을 새로 만들었다.
settings.py
에 INSTALLED_APP
부분에서 기존에 사용했던 app을 제거<project-name>/urls.py
에서 기존에 사용했던 url을 모두 지워준다account
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
comment
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
새롭게 구성한 앱의 tree구조는 위와 같고 해당 app에 맞춰서 urls.py
를 수정해주고 각 app에서도 URLConf 설정을 진행한다.
# westargram_api/urls.py
from django.urls import path, include
urlpatterns = [
path('account', include('account.urls')),
path('comment', include('comment.urls'))
]
# westargram_api/settings.py 중에서
INSTALLED_APPS = [
# 'django.contrib.admin',
# 'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'account',
'comment',
]
먼저 account에서 models.py
를 아래와 같이 구성한다. 실제 GET, POST 사용법에 맞춰서 아래와 같이 구현할 수 있다.
# account/models.py
from django.db import models
class Account(models.Model):
user_account = models.CharField(max_length=50),
password = models.CharField(max_length=300)
created_at = models.DateTimeField(auto_now_add=True),
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'user_account'
# account/urls.py
from django.urls import path
from .views import SignUpView, SignInView
urlpatterns = [
path('/sign-up', SignUpView.as_view()),
path('/sign-in', SignInView.as_view())
]
# comment/models.py
from django.db import models
class Comment(models.Model):
user_account = models.CharField(max_length=50),
comments = models.CharField(max_length=700)
created_at = models.DateTimeField(auto_now_add=True),
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'user_comment'
# comment/urls.py
from django.urls import path
from .views import CommentView
urlpatterns = [
path('', CommentView.as_view()),
]
다음으로 views.py
를 마저 완성시켜 준다. 기존에 작성했던 api의 로직과는 크게 차이가 없고 app을 나누고 예외처리를 해줄 부분을 해주게 되면 아래와 같다.
# account/views.py
import json
from django.views import View
from django.http import HttpResponse, JsonResponse
from .models import Account
class SignInView(View):
def post():
account_data = json.loads(request.body)
try:
if Account.objects.filter(user_account=account_data['user_account']).exists():
account = Account.objects.get(user_account=account_data['user_account'])
if account.password == account_data['password']:
return JsonResponse({'message':'Welcome back!'}, status=200)
return HttpResponse(status=401)
return HttpResponse(status=400)
except KeyError:
return HttpResponse(status=400)
class SignUpView(View):
def post(self, request):
account_data = json.loads(request.body)
try:
if not Account.objects.filter(user_account=account_data['user_account']).exists():
Account(
user_account=account_data['user_account'],
password=account_data['password']
).save()
else:
return HttpResponse(status=409)
except KeyError:
return HttpResponse(status=400)
return JsonResponse({'message':'SUCCESS'}, status=200)
실제로 테스트를 진행하기 위해 python manage.py sqlmigrate
명령어를 실행하여 아래와 같은 작업을 진행
>>> Account.objects.create(user_account='abc', password=1234)
>>> Account.objects.all().values()
<QuerySet [{'id': 1, 'user_account': 'abc', 'password': '1234', 'created_at': datetime.datetime(2020, 2, 8, 11, 20, 11, 842314, tzinfo=<UTC>), 'updated_at': datetime.datetime(2020, 2, 8, 11, 20, 11, 842371, tzinfo=<UTC>)}]>
>>> Account(user_account='bcd', password=4567).save()
>>> Account.objects.all().values()
<QuerySet [{'id': 1, 'user_account': 'abc', 'password': '1234', 'created_at': datetime.datetime(2020, 2, 8, 11, 20, 11, 842314, tzinfo=<UTC>), 'updated_at': datetime.datetime(2020, 2, 8, 11, 20, 11, 842371, tzinfo=<UTC>)}, {'id': 2, 'user_account': 'bcd', 'password': '4567', 'created_at': datetime.datetime(2020, 2, 8, 11, 22, 13, 846972, tzinfo=<UTC>), 'updated_at': datetime.datetime(2020, 2, 8, 11, 22, 13, 847010, tzinfo=<UTC>)}]>
urls.py
설정에 유의 ! <url이름>/ or <url 이름>으로 할 것그렇지 않으면 404 NOT Found가 뜨면서 테스트 자체가 안되었다. urlpatterns 명시에 주의. project 상단에서 app까지 어떻게 이어지는지 잘 생각해서 패턴을 명시할 것.
# comment/views.py
import json
from django.views import View
from django.http import HttpResponse, JsonResponse
from .models import Comment
class CommentView(View):
def post(self, request):
comments_data = json.loads(request.body)
Comment(
user_account=comments_data['user_account'],
comments=comments_data['comments']
).save()
return JsonResponse({'message':'SUCCESS'}, status=200)
def get(self, request):
return JsonResponse({'comments':list(Comment.objects.values())}, status=200)
comment 앱 부분도 다음과 같이 명시해 주고 테스트들을 하면 다음과 같은 결과를 얻을 수 있었다.
$ http -v http://127.0.0.1:8000/account/sign-in user_account=abc password=1234
POST /account/sign-in HTTP/1.1
Accept: application/json, */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 43
Content-Type: application/json
Host: 127.0.0.1:8000
User-Agent: HTTPie/2.0.0
{
"password": "1234",
"user_account": "abc"
}
HTTP/1.1 200 OK
Content-Length: 28
Content-Type: application/json
Date: Sat, 08 Feb 2020 12:18:13 GMT
Server: WSGIServer/0.2 CPython/3.8.1
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"message": "Welcome back!"
}
$ http -v http://127.0.0.1:8000/account/sign-in user_account=bcd password=45
POST /account/sign-in HTTP/1.1
Accept: application/json, */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 41
Content-Type: application/json
Host: 127.0.0.1:8000
User-Agent: HTTPie/2.0.0
{
"password": "45",
"user_account": "bcd"
}
HTTP/1.1 401 Unauthorized
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Sat, 08 Feb 2020 12:20:35 GMT
Server: WSGIServer/0.2 CPython/3.8.1
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
$ http -v http://127.0.0.1:8000/account/sign-up user_account=abc password=5678
POST /account/sign-up HTTP/1.1
Accept: application/json, */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 43
Content-Type: application/json
Host: 127.0.0.1:8000
User-Agent: HTTPie/2.0.0
{
"password": "5678",
"user_account": "abc"
}
HTTP/1.1 409 Conflict
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Sat, 08 Feb 2020 12:21:39 GMT
Server: WSGIServer/0.2 CPython/3.8.1
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
$ http -v http://127.0.0.1:8000/account/sign-up user_account=efg password=5678
POST /account/sign-up HTTP/1.1
Accept: application/json, */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 43
Content-Type: application/json
Host: 127.0.0.1:8000
User-Agent: HTTPie/2.0.0
{
"password": "5678",
"user_account": "efg"
}
HTTP/1.1 200 OK
Content-Length: 22
Content-Type: application/json
Date: Sat, 08 Feb 2020 12:21:53 GMT
Server: WSGIServer/0.2 CPython/3.8.1
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"message": "SUCCESS"
}
$ http -v http://127.0.0.1:8000/comment user_account=def comments=hajdhklfjasdklfjldsk
POST /comment HTTP/1.1
Accept: application/json, */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 59
Content-Type: application/json
Host: 127.0.0.1:8000
User-Agent: HTTPie/2.0.0
{
"comments": "hajdhklfjasdklfjldsk",
"user_account": "def"
}
HTTP/1.1 200 OK
Content-Length: 22
Content-Type: application/json
Date: Sat, 08 Feb 2020 12:15:46 GMT
Server: WSGIServer/0.2 CPython/3.8.1
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"message": "SUCCESS"
}
$ http -v http://127.0.0.1:8000/comment user_account=dgdgd comments=gotohell
POST /comment HTTP/1.1
Accept: application/json, */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 49
Content-Type: application/json
Host: 127.0.0.1:8000
User-Agent: HTTPie/2.0.0
{
"comments": "gotohome",
"user_account": "dgdgd"
}
HTTP/1.1 200 OK
Content-Length: 22
Content-Type: application/json
Date: Sat, 08 Feb 2020 12:16:25 GMT
Server: WSGIServer/0.2 CPython/3.8.1
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"message": "SUCCESS"
}
http -v http://127.0.0.1:8000/comment
GET /comment HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: 127.0.0.1:8000
User-Agent: HTTPie/2.0.0
HTTP/1.1 200 OK
Content-Length: 312
Content-Type: application/json
Date: Sat, 08 Feb 2020 12:16:28 GMT
Server: WSGIServer/0.2 CPython/3.8.1
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"comments": [
{
"comments": "hajdhklfjasdklfjldsk",
"created_at": "2020-02-08T12:15:46.264Z",
"id": 1,
"updated_at": "2020-02-08T12:15:46.264Z",
"user_account": "def"
},
{
"comments": "gotohome",
"created_at": "2020-02-08T12:16:25.028Z",
"id": 2,
"updated_at": "2020-02-08T12:16:25.028Z",
"user_account": "dgdgd"
}
]
}