21.12.27 Django 튜토리얼 Part4 폼 쓰기, 제너릭 뷰 사용

2021. 12. 27. 21:00작업/Django

detail.html을 수정해서 <form>태그를 포함해보자

- 여기서 forlooop.counter는 for 태그가 반복을 한 횟수를 말한다.

- 우리는 우리의 form의 method를 post로 했기 때문에 get방식처럼 url에 전달하는 게 아닌 새로운 리소스에 숨겨서 전달한다.

- 그리고 post방식을 사용하기 때문에 크로스 사이트 요청 frogeries에 유의해야 한다. 모든 POST form은 {% csrf_token %} 을 템플릿 테그에 사용해야 한다.

request.POST는 키로 전송된 자료에 접근할 수 있도록 해주는 객체이다. key,value존재

request.POST['choice'] 는 선택된 설문의 ID를 문자열로 반환한다.

request.POST의 값은 항상 문자열이다.

 

- 만약 POST자료에 choice가 없으면 request.POST['choice'] 는 KeyError가 일어난다. try except 문으로 KeyError를 체크하고 choice가 주어지지 않는 경우에 에러 메시지와 함께 설문조사 폼을 다시 보여준다.

 

- (selected_choice.vote) 설문지의 수가 증가한 이후 코드는 일반 HttpResponse가 아닌 HttpResponseRedirect( 재전송 될 URL ) 함수를 실행한다.

 

- 이 예제에서 reverse()라는 함수도 사용하는데, 이 함수는 뷰 함수에서 URL을 하드코딩하지 않도록 도와준다. 

즉 reverse() 호출은 '/polls/1/results' 와 같은 문자열을 반환한다.

 

- 이렇게 리디렉션된 URL은 최종 페이지를 표시하기 위해 results 뷰를 호출한다.

 

근데 results 페이지가 이렇게 못생겼으니 def result()함수와 results.html을 손봐주자

views.py

그러나 우리가 만든 이 vote 뷰에는 작은 문제가 있다. 우리는 vote를 계산할 때 먼저 데이터베이스에서 selected_choice 객체를 가져온 다음 votes의 새 값을 계산하고 나서 데이터베이스에 다시 저장하는데

만약 두 명의 유저가 정확히 같은 시간에 투표를 시도할 경우 조회값이 한 명한테는 30으로 한명한테는 31으로 계산이 되고 저장된다. 그러나 실제로는 2개가 증가한 32가 되어야 한다.

 

이런 상태를 경쟁 상태라고 하며, 이를 피하려면 race condition을 피해야 한다.(이거 운영체제 시간에 배웠던 기억이..가물가물하게 난다 ㅋㅋ)

 

제너릭 뷰 사용하기: 적은 코드가 더 좋다

views.py
urls.py question_id를 pk로 바꿨다.그리고 자주 쓰이는 뷰는 저런 generic view를 사용한듯

 

이렇게 제너릭뷰를 써도 마찬가지로 잘 작동된다.

여기서는 ListView와 DetailView 두 가지 제너릭 뷰를 사용한다.

- DetailView 제너릭 뷰는 URL에서 캡처된 기본 키 값이 pk라고 기대하기 때문에 question_id를 제너릭 뷰를 위해 pk로 변경한다.

- 기본적으로 제너릭 뷰는 앱이름/모델이름_detail.html 템플릿을 사용한다.