본문 바로가기
source-code/Django

PNU Quiz App _ django로 퀴즈 구현하기2

by mattew4483 2021. 2. 1.
728x90
반응형

얼마 전 만든 PNU Quiz App.

실제 배포 환경에서 기존 방법에 어마 무시한 문제가 있어... 기능을 아예 새롭게 작성했다.

처음부터 이게 맞는 방향이었을 것 같은데... 괜히 쉬운 길을 택하려다 낭패를 봤다.

 

어쨌든 이렇게 작성한 코드를 리뷰해볼 예정!

구현된 페이지!


1. 기존 방법 수정하기.

views.py

기존에는 유저가 각 보기를 클릭하고, 다음 버튼을 누르면, 

해당 버튼의 value(보기의 내용)를 url에 담아 전달해주는 방법을 사용했다.

 

즉 어딘가에 저장되는 것도, 실제 선택이 제출되는 것도 아니었다!

(그냥 url에 담긴 value를 받아와 view에서 해당 value를 list안에 넣어주기만 했다)

 

이렇게 작성하고 나니...

유저의 정답이 담긴 list는 각 응답을 저장할 때, 그리고 점수를 매길 때 사용돼야 한다.

물론 이 둘은 각기 다른 함수를 통해 작동한다. 따라서 list는... view의 최상위에 전역으로 설정되어야 했다!

이런 식으로

이렇게 배포를 하니... 세상에나, 서로 다른 유저가 한 view의 list를 공유하는게 아닌가!(사실 당연한 것)

즉 A가 체크한 정답이 다른 접속 환경의 B에게도 영향을 미치고 말았다.

이래서는 퀴즈라고 할 수가 없다!!! 따라서 해당 내용을 전면 수정.

 

2. Form을 통해 제출하기

그럼 어떻게 해야 하는가!

가장 직관적이면서도 정석인 방법... form의 submit을 이용하기로 했다.

 

즉 사용자가 퀴즈를 시작할 때마다 새로운 모델 object들을 생성하고,

이용자가 클릭해 제출한 값을 각 object안에 넣은 후,

결과 페이지에서 이용자가 제출한 값들과 정답을 비교해 점수를 매기는 것!

 

3. model 수정

models.py

총 3개의 모델을 만들었다.

제일 먼저 진짜 정답들이 담겨있는 Answer 모델(얘는 맨 마지막 체점시 사용된다).

다음은 이용자에게 띄워줄 질문과 보기들이 담긴 Question 모델.

마지막으로 이용자의 제출한 응답을 저장할 PnuUser모델(말만 user지 django의 user와는 아무런 관련이 없다).

 

즉 이용자가 퀴즈를 시작하면 자동적으로 새로운 PnuUser 모델이 하나 생성되고,

이용자가 퀴즈를 풀 때마다 제출한 답이 PnuUser의 answer이라는 필드 안에 저장되고,

퀴즈 종료 시 PnuUser의 answer이라는 필드에 담긴 답과 Answer이라는 모델에 담긴 정답(ans필드)을 비교!

 

4. view 작성

views.py

총 3개의 함수가 사용된다.

첫 페이지와 PnuUser생성을 담당할 home.

html상에 Question들을 띄워주고, 이용자의 응답을 저장하며, 정답과 비교해 점수를 매겨주는 quiz.

결과 화면을 띄워주고 전체 유저의 평균 점수를 구하는 result.

 

1) home

views.py

제일 먼저 home.

첫 화면인 home.html을 띄워주고, GET요청 시(문제 풀기 클릭 시) PnuUser를 생성한다.

이때 PnuUser의 name은 이용자가 input상에 기입한 이름.

아무것도 적지 않았을 시 그냥 "익명"이라는 이름으로 PnuUser가 생성된다.

save를 완료한 후 quiz함수로 redirect!

 

2) quiz

veiws.py

각 Question들을 template상에 띄워주는 quiz함수.

여기서 정말 획기적인 방법이 등장한다.

 

우리가 원하는 건? 한 페이지 당 하나의 Question을 띄워주는 것!

그런데 평소 하던 것처럼 Question.objects.all()을 context에 담아 보내주면...

for문을 돌며 모든 Question들이 template상에 띄워지게 된다!

 

그렇기 때문에... Question 중 id가 num인 녀석만을 가져와 template상에 띄워준다!

그리고 요 num는 이용자가 POST 요청을 보낼 때마다, 즉 한 문제를 풀 때마다 하나씩 늘어난다.

즉 각 페이지 별로 n번 째 Question 하나만 template상에 존재하는 것! 와우!

 

views.py

요 녀석은? 정답을 체점하는 코드!

이게 당최 무슨 소리??? 이를 알기 위해서는 admin페이지에 접속해야 한다.

 

우리가 생성한 model은 3개!

Answer에는 진짜 정답이 담겨 있고, PnuUser에는 이용자가 제출한 답이 담겨있다!

 

Answer 모델
PnuUser 모델

아하! 즉 user.answer = user.answer + request.POST['answer'] 를 통해

PnuUser의 answer필드에 request.POST['answer'] (얘는 이용자가 제출한 답) 를 넣어주는 것!

 

request.POST['answer']가 제출될 때마다 정답이 담긴 문자열과 비교해 num-2번째와 같으면 1점 더하기!

 

3) result

제일 별 기능이 없는 함수!

for문과 if문은 각각 유저 전체 점수의 평균과 에러 페이지를 위해 만들었는데...

사실 없어도 무관하다! 요는 result.html을 띄우는 것!

 

5. templates 작성

home.html

제일 첫 화면인 home.html!

 

이 부분을 클릭하면 아까 전 home 함수가 실행되며 PnuUser라는 모델이 생성된다.

 

quiz.html

쨔잔. Question 모델 안에 있는 option 1~4를 각각 form에 담아 보내준다!

hidden으로 숨겨둔 녀석들은 각각 문제 번호와 답 저장을 위해 숫자 형태를 보내주는 것!

이용자가 봐야하는 값은 {{quiz.option1~4}}이므로 나머지는 hidden으로 숨겼다.

 

result.html

각 이용자의 점수, 즉 {{user.score}}에 따라 다른 콘텐츠를 보여줘야 한다.

이를 위해 html 템플릿의 if문을 사용, score의 범위에 따라 다른 요소를 넣어줬다.

 

6. urls 작성

urls.py

url 작성. 별다른 건 없다!


사실 기존에 알고 있는 지식들 만으로도 충분히 작성이 가능했다..!

하지만 괜히 다른 걸 따라한다고 이상한 걸 참고하는 바람에... 애먼 시간을 날리고 말았다.

역시 자신이 완전히 이해할 수 있는, 근거가 있는 코드를 작성해야 한다.

 

어쨌든, 이렇게 작성하고 나면 기능적인 부분은 구현이 완료!

하지만 html과 css로만 이뤄진 웹페이지는... 영 심심하다.

여기서 js가 출동한다.

728x90
반응형