티스토리 뷰
첫 번째 장고 앱 작성하기, 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/ 페이지로 가서, 투표를 해보세요.
투표를 할 때마다 값이 반영된 결과 페이지를 볼 수 있을 것입니다.
만약 설문지를 선택하지 않고 폼을 전송했다면, 오류 메시지를 보게 될 것입니다.
'🐍 > Django' 카테고리의 다른 글
[Django] HTTP Request를 받아서 응답해주기 (GET, POST, PUT, DELETE) (1) | 2020.02.16 |
---|---|
[Django] 튜토리얼 part 4 (2) - Generic view 사용하기 (0) | 2020.02.15 |
[Django] 튜토리얼 part 3 (2) - 404 에러 일으키기, get_object_or_404, {% url %} 템플릿 태그 (0) | 2020.02.11 |
[Django] 튜토리얼 part 3 (1) - view 만들기, Template 이용하기, r (0) | 2020.02.11 |
[Django] 에디터(Atom, VSCode)에 파이썬 & 장고 자동완성 기능 추가하기 (1) | 2020.02.11 |
- Total
- Today
- Yesterday
- Django Heroku Scheduler
- flutter deep link
- github actions
- cocoapod
- flutter dynamic link
- Flutter Clipboard
- Django FCM
- Flutter 로딩
- Flutter Spacer
- PencilKit
- 장고 Custom Management Command
- Django Firebase Cloud Messaging
- 장고 URL querystring
- SerializerMethodField
- Sketch 누끼
- flutter build mode
- 구글 Geocoding API
- 플러터 싱글톤
- Python Type Hint
- 플러터 얼럿
- METAL
- Dart Factory
- DRF APIException
- ribs
- Flutter getter setter
- drf custom error
- Watch App for iOS App vs Watch App
- Flutter Text Gradient
- flutter 앱 출시
- ipad multitasking
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |