# accounts/models.py
from django.db import models
from users.models import User
class Account(models.Model):
amount = models.PositiveIntegerField(verbose_name="금액")
memo = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="작성자")
is_delete = models.BooleanField(default=False, verbose_name="삭제여부")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="작성시간")
updated_at = models.DateTimeField(auto_now=True, verbose_name="수정시간")
def __str__(self):
return f"{self.amount}: {self.memo[:20]}"
# accounts/view.py
class AccountDetail(APIView):
...
def delete(self, request, pk):
"""
가계부 삭제
DELETE /api/v1/accounts/<pk>/
"""
user = request.user
account = self.get_account(pk=pk, author=user)
delete = {"is_delete": "true"}
serializer = serializers.AccountsIsDeleteSerializer(account, data=delete)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_204_NO_CONTENT)
return Response(status=status.HTTP_400_BAD_REQUEST)
is_delete : true로 변경해 준다.# users/models.py
from django.contrib.auth.models import AbstractUser, User
from django.db import models
class User(AbstractUser):
"""
TODO
email -> password reset 인증에 사용 예정
"""
username = models.EmailField(max_length=150, unique=True, verbose_name="username")
first_name = models.CharField(max_length=30, editable=False)
last_name = models.CharField(max_length=30, editable=False)
name = models.CharField(max_length=100, verbose_name="name")
phone = models.CharField(max_length=20, verbose_name="phone")
def __str__(self):
return self.username
# users/views.py
class Login(APIView):
def post(self, request):
user = authenticate(
username=request.data.get("username"), password=request.data.get("password")
)
if user is not None:
serializer = serializers.UsersSerializer(user)
token = TokenObtainPairSerializer.get_token(user)
refresh_token = str(token)
access_token = str(token.access_token)
response = Response(
{
"user": serializer.data,
"message": "login success",
"token": {
"access": access_token,
"refresh": refresh_token,
},
},
status=status.HTTP_200_OK,
)
return response
else:
return Response(status=status.HTTP_400_BAD_REQUEST)
class Logout(APIView):
def post(self, request):
"""
로그아웃
POST /api/v1/users/logout/
"""
try:
refresh_token = request.data["refresh"]
token = RefreshToken(refresh_token)
token.blacklist()
return Response(status=status.HTTP_205_RESET_CONTENT)
except Exception as e:
return Response(status=status.HTTP_400_BAD_REQUEST)
웹 개발을 처음 배울 때 블로그를 만들어보았다. 게시글을 삭제하는 방법도 있지만 비활성화하는 방법도 있다는 것을 듣고 구현해 본 경험이 있다. 그때의 경험이 이번 가계부 삭제/복구 기능을 구현하는데 좋은 발판이 되었다. 역시 경험만큼 좋은 solution은 없는거 같다.
DRF에서 지원하는 인증에는 SessionAuthentication, BasicAuthentication, TokenAuthentication 세 가지가 있다. 이 세 가지 중 Token을 사용해 보았다. 초기 로그인 시에 username/password로 Token을 발급하고, 이 Token을 매 API 요청에 담아서 보내어 인증을 처리한다. 하다보니 JWT Token과 DRF의 Token을 혼동하며 사용했다는 기분이 들었다. 다음엔 JWT Token을 이용하여 명확하게 구현을 해볼 생각이다.