퀴즈 싱글플레이 부분에서 콘솔창을 이용해서 점수를 우다다 올리는 경우가 생겼는데 ^.^...
프로젝트가 바닐라 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)
...
퀴즈 정보 처리를 끝낸 뒤,
isinstance
로 AnonymousUser(비로그인)
구분을 해주고
로그인 한 경우 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
에 담긴다!
isinstance와 request.user, AnonymousUser를 조합한건 기막힌 작성법이네요. 하나 새로 배웠습니다.