티스토리 뷰

728x90
반응형

첫 번째 장고 앱 작성하기, part 4 를 따라해본 것을 기록 😎

4장에서는  Web-poll application을 마저 만들고 코드를 줄이는 것을 배워본다고 합니다.  

 

http://localhost:8000/polls/1/  (1은 question_id) 

이 스타일의 URL로 접속할 때 보여주는 투표 상세 템플릿("polls/detail.html")을 수정하여, 템플릿에 HTML <form> 요소를 포함시켜 봅시다. 

 

polls > detail.html을 아래와 같이 변경해주세요 

 

 

이런 화면을 보여주는 코드 입니다. 

 

이 라인에 주목해주세요 

<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">

 

각 질문이 있고 선택할 수 있는 항목들(choice들)이 쭉 있는데, 선택항목들을 라디오 버튼으로 표시하네요 

각 라디오 버튼의 value는 연관된 choice의 ID입니다. 각 라디오 버튼의 name  "choice"입니다.

 

이 라디오 버튼들은 form안에 있습니다. 

<form action="{% url 'polls:vote' question.id %}" method="post">
     라디오 버튼들~ 
     <input type="submit" value="Vote">
</form>

 

누군가가 라디오 버튼 중 하나를 선택하고 submit을 눌러서 폼을 제출하면, POST 데이터 인 choice=#을 보낼 것입니다.

여기서 #은 선택한 choice의 ID입니다.

HTML 폼의 기본 작동방식이라고 하네요 :-) 

 

그리고 forloop.counter  for 태그가 반복을 한 횟수를 나타낸다고 합니다. 

 

이 라인의 윗윗줄 csrf_token 의 

csrf는 Cross Site Request Forgeries 의 약자인데요,

Cross Site Request Forgery (사이트 간 요청 위조?!?) 가 정확히 뭔지 모르겠지만 

이것을 막아주는 역할을 해준다고 합니다 

 

 

 

그 다음 이 코드를 주목해주세요 

<form action="{% url 'polls:vote' question.id %}" method="post">

 

 

form의 action을  {% url 'polls:vote' question.id %} 이라고 정했습니다. 

method는 post인데, 이것은 매우 중요하다고 합니다. server-side의 데이터를 바꾸기 때문이죠

 

 

그리고 vote라는 이름의 URLpattern은 polls > urls.py에 정의 되어있습니다. 

 

 

polls > views.py 에 가보면 vote 라는 함수도 이렇게 임시로 정의해놨습니다. 

 

 

vote함수를 실제로 구현해주겠습니다. 

우선  import해야할 것을 해주세요

 

 

 

하나씩 살펴볼게요...!!

1) 우선 question_id라는 primary key를 기준으로 일치하는 Question을 가져옵니다.

 

2) Question의 choice_set (아직 모델에서 정의안해줬음) 에서 choice를 가져오는데요 

어떤 기준으로 가져오냐면....!! post request 에서 준 choice라는 value와 일치하는 primary key를 가진 Question을 가져옵니다

 

request.POST 는 키로 전송된 자료에 접근할 수 있도록 해주는 사전과 같은 객체입니다.

이 경우, request.POST['choice'] 는 선택된 Choice의 ID를 문자열로 반환합니다. request.POST 의 값은 항상 문자열들이라고 하네요. 

Post에 대해서 아래에서 더 알아볼게요...!! 

QueryDict objects

HttpRequest object인  GET 과 POST attributes 는 django.http.QueryDict 의 인스턴스라고 합니다. 

QueryDict은 딕셔너리 같은 것이라고 합니다. 

키에 multiple values를 전달할 수 도 있다고 합니다. 

예를 들어 아래 처럼 a라는 같은 키값으로, a=1 과 a=2를 같이 보낸다고 하면  

'a' : ['1', '2']  이렇게 해주는 것입니다. 

 

저렇게 동작하는 것을 보니

위의 "choice=id" 로 들어온 post 요청를 key는 choice, value는 id 인 딕셔너리로 변환시켜줘서

우리가 request.Post['choice'] 로 id 값을 구했던 것이 이해가 가네요 :-) 

 

 

3) 만약 POST 요청에 choice 가 없으면, request.POST['choice']  KeyError 가 일어납니다.

위의 코드는 KeyError 를 체크하고, choice가 주어지지 않은 경우에는 에러 메시지와 함께 설문조사 폼을 다시보여줍니다.

 

4) Exception이 발생하지 않으면 choice의 숫자를 증가시킨 이후에, 코드는 일반 HttpResponse 가 아닌 HttpResponseRedirect 를 반환하고, 
HttpResponseRedirect 는 하나의 인수를 받습니다. 그 인수는 선택을 끝낸 사용자에게 보여줄 결과화면의  URL 이라고 합니다. 

( 어떤 이가 설문조사에 설문을 하고난 뒤에는, vote() 뷰는 설문조사 결과 페이지로 리다이렉트합니다. )

 

5)  HttpResponseRedirect 생성자 안에서 reverse() 라는 함수를 사용하고 있습니다.

 

reverse함수는 이런 함수입니다.

 

 

저희가 구현한 이 코드에서는 viewname과 args 를 쓰고 있습니다.

args는 "The arguments that would be passed to the view function, as parsed from the URL." 이라고 설명이 적혀있네요

 

reverse('polls:results', args=(question.id,))

 

 

reverse 함수를 쓰는 이유는 뷰 함수에서 URL을 하드코딩하지 않도록 하기 위해서 입니다.
제어를 전달하기 원하는 뷰의 이름과 URL패턴의 변수부분을 조합해서 해당 뷰를 가리킵니다.

 

저 함수를 호출하면 urlpatterns에서 name이 results인 것을 찾게 될 것이고 

 

 

아래와 같은 문자열을 반환하게 될 것입니다.

'/polls/3/results/'

 

여기서 3  question.id 값입니다. 이렇게 리디렉션된 URL은 최종 페이지를 표시하기 위해 'results' 뷰를 호출합니다. 

 

 

Result 뷰 만들기

 

이제 Result뷰를 구현해줍시다. 

polls > urls.py 에 가보면 urlpattern도 정의되어있고 

 

 

polls > views.py에 가보면 뷰함수도 임시로 구현되어있습니다. 

 

 

이렇게 실제 구현으로 바꿔주세요 

question_id에 해당하는 Question을 가져와서 results.html를 렌더링 해줍니다. 

 

 

results.html은 없으니까 작성해야합니다.

polls > templates >polls 디렉토리에서 results.html을 만들어주세요 

 

 

이런 화면을 보여주는 코드 입니다

 

 

이제 웹 브라우저에서 /polls/1/ 페이지로 가서, 투표를 해보세요.

투표를 할 때마다 값이 반영된 결과 페이지를 볼 수 있을 것입니다.

만약 설문지를 선택하지 않고 폼을 전송했다면, 오류 메시지를 보게 될 것입니다.

 

반응형
댓글