2023-07-04 TIL

0v0baek·2023년 7월 4일
1

TIL

목록 보기
89/92

[django] 퀴즈 타임스탬프 기능

퀴즈 싱글플레이 부분에서 콘솔창을 이용해서 점수를 우다다 올리는 경우가 생겼는데 ^.^...

프로젝트가 바닐라 JS기도 하고 사실 그런 코드 자체를 원천적으로 막을 방법은 지금 상황에서는 없다고 판단,

대신 퀴즈 타임 스탬프 기능을 만들었다.

❓ 타임 스탬프

타임스탬프라 함은 시간 표기는 특정한 시각을 나타내거나 기록하는 문자열이라고 한다.

그럼 현 프로젝트에서 타임 스탬프가 무슨 기능을 하나!
퀴즈를 받아오고 풀어서 서버에 제출할 때 마다 하나의 타임스탬프 기록을 생성해 DB에 저장한다.

비정상적으로 많은 요청이 들어오는 걸 한눈에 파악 가능하게 만들어주는 거다.

✅ 코드

👀 백엔드

# users/models.py

class UserTimestamp(models.Model):
    user = models.ForeignKey(User, related_name="timestamp", on_delete=models.CASCADE)
    quiz_start = models.DateTimeField(auto_now_add=True)
    quiz_end = models.DateTimeField(null=True)

퀴즈 정보를 기록해 줄 model을 만들어주자.

# crawled_data/views.py

from users.models import UserTimestamp
from django.contrib.auth.models import AnonymousUser


class PuzzleCreateView(APIView):
    def get(self, request):
        ...
        퀴즈 정보 처리
        ...
        if not isinstance(request.user, AnonymousUser):
            UserTimestamp.objects.create(user=request.user)
        ...

퀴즈 정보 처리를 끝낸 뒤,
isinstanceAnonymousUser(비로그인) 구분을 해주고
로그인 한 경우 UserTimestamp 객체를 새로 생성해준다.

# quizzes/views.py

from users.models import UserTimestamp
from django.utils import timezone


class QuizResultView(APIView):
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request):
        ...
        if serializer.is_valid():
            ...
            timestamp = (
                UserTimestamp.objects.filter(user=request.user)
                .order_by("-quiz_start")
                .first()
            )
            if timestamp:
                timestamp.quiz_end = timezone.now()
                timestamp.save()
            ...

게임 결과 처리 뷰에서 퀴즈가 끝나는 시점을 저장해준다.
serializer가 유효한 경우에만 업데이트 한 뒤 save할 수 있게 해준다.

👀 프론트엔드

// api.js

export async function getQuizApi(type) {
  let responseJson;
  let link;
  const token = localStorage.getItem("access");
  if (!type) {
    link = `${BACK_BASE_URL}/DB/gen/`;
  } else {
    link = `${BACK_BASE_URL}/DB/gen/?type=${type}`;
  }
  const headers = token ? { Authorization: `Bearer ${token}` } : {};
  const response = await fetch(link, { headers });
  if (response.status === 200) {
    responseJson = await response.json();
  } else if (response.status === 500) {
    window.location.reload();
  }
  return responseJson;
}

퀴즈를 가져올 때 로그인 되어있는 상태면 token값을 header에 실어서 보내준다.
아닌 경우에는 비워서 보내준다.

🔎 결과

이렇게 유저의 퀴즈 시도 기록이 고스란히 DB에 담긴다!

profile
개발 공부 하는 비전공자 새내기. 꾸준히 합시다!

1개의 댓글

comment-user-thumbnail
2023년 7월 5일

isinstance와 request.user, AnonymousUser를 조합한건 기막힌 작성법이네요. 하나 새로 배웠습니다.

답글 달기