전체 흐름
1. mysite project생성 -> polls app 생성
2. model 생성
3. urls 작성
4. 각 views & templates 작성
2. model 생성
models.py
직업, 선호, 지역을 물어볼 Question모델을 만든다.
DateTimeField에 정의한 'date published'는? 이후 admin에서 보게 될 문구!
각 Question(ex 직업이 무엇인가요?)마다 해당되는 Choice(ex 독서, 축구, 등산)가 필요하다.
즉 Question모델과 Choice모델을 Foreignkey로 상호참조.
여기서 ForeignKey는 항상 다른 모델의 PK와 연결되므로, Question의 id변수까지 지정할 필요가 없다.
(그냥 Question 클래스만 지정하면 됨)
이렇게 FK로 지정된 컬럼은 _id 접미사가 붙는다!!
다르게 말하자면, _id가 붙은 녀석들은 FK로 지정된 Choice모델의 question칼럼이란 말씀.
투표를 할 때마다 해당 Choice들의 숫자가 올라가므로 이를 나타내줄 IntergerField도 생성한다.
3. urls 작성
urls.py
path()는 기본적으로
첫번째 인자 -> 요청 받을 url
두번째 인자 -> 해당 url 요청시 작동될 함수
세번째 인자 -> 코드 내에서 지칭해줄 이름 으로 이해하면 쉽다.
즉 path('polls/<int:question_id>/', detail, name='detail') 의 경우
요청 url이 polls/3/ 이면 views함수 호출 시 detail(request, questions_id=3)이 작동되고, 그 이름을 detail로 지어준 것!
여기서 int:question_id는 index.html에서 보내줄, 각 질문의 pk값이 되겠다.
4. Views & Templates 작성
1) index함수 & index.html 작성
views.py
Questions모델의 모든 dbjects들을 index.html에 뿌려준다!
이를 위해 Questions.objects.all() 사용.
뒤에 order_by('-pub_date') 는 칼럼이 만들어진 날짜인 pub_date의 역순(-)으로 정렬order하겠다는 뜻이다.
index.html
{% if latest_question_list %} -> 넘겨준 Questions.objects.all()일 경우 아래의 for문을 작동!
그 외의 경우(else) -> No Polls are available 이란 문구를 보여준다.
for문을 통해서는 Questions모델에 있는 quetions_text들을 하나하나 띄워줘야 한다.
즉 {% for question in latest_quetion_list %}를 통해 for문을 돌려주고,
{{question.question_text}} 를 통해 latest_question_list의 요소들 중 question_text를 하나씩 띄워준다!
각 question_text를 클릭하면 해당 질문에 맞는 detail 페이지로 이동해야한다.
따라서 a herf를 통해 링크를 걸어주고,
링크를 클릭하면 .../polls/해당 질문 id 라는 주소로 이동하도록 한다.
그리고 이는 아까 url 에서
요 녀석에 해당된다. 즉 이를 통해 detail 함수를 작동시키는 것!
그럼 이제 detail 함수와 페이지를 만들어보자.
2) detail함수 & detail.html 작성
views.py
detail 함수를 통해 각 Question 모델에 대응하는 choice들을 띄워줘야 한다.
이를 위해서는 Question 모델 각각의 고유 값들을 찾은 후, 고유 값에 해당되는 choice들을 가져와야한다.
'question_text의 고유 값' -> 이 녀석이 urls을 통해 보내준 question_id가 되는 것!
즉 get_object_or_404를 통해 Question모델에서 pk=question_id인 녀석들을 찾는다.
조건에 해당되는 객체가 없을 경우에는 404에러 반환!
detail.html
{{question.question_text}} -> 우선 해당 질문(question_text)을 띄워준다.
error_message -> 이 부분은 이후 vote에서 다룰 예정!
detail 페이지에서는 각 질문들에 대한 응답을 제출하는 기능이 필요하다. 이를 위해 우선 form태그 사용.
제출 시 (아직 만들지 않은) vote 함수가 작동해 해당 응답들을 count하게 해줄 예정이다.
{% url 'vote' question.id %} -> 요 녀석을 통해 vote url에 question의 id를 보내서 전달!
POST요청을 사용하기 때문에 밑에 {% csrf_token %} 도 야무지게 적어준다.
다음으로 모델에 담겨있는 항목들을 불러와 투표할 수 있도록 해야한다.
{% for choice in question.choice_set.all %}을 통해
Question모델(detail함수를 통해 question이란이름으로 html에 뿌려줬다)의 choice_set 속성에 든 항목 모두를 가져온다.
여기서 choice_set의 정체는?
현재 Choice모델은 Question과 ForeignKey로 연결된 상태.
우리는 question으로 연결된 Choice모델을 칼럼들을 가져오고 싶다!
이 때 사용하는 django의 기본값이 바로 _set.all이라고 생각하면 된다.
input type="radio"를 통해 해당 radio 버튼을 클릭하면,
POST 데이터가 'choice' = '3' (choice.id)과 같은 형태가 되도록 name과 value를 정의해준다.
{{choice.choice_text}}를 통해 for문을 돌며 받아온 choice내의 choice_text속성들을 하나하나 띄워준다.
마지막으로 이를 제출할 input type="submit"과 value를 입력.
이제 vote버튼을 누르면 작동될, 각 항목별 투표수를 세어주는 함수를 만들어 보자.
3) vote함수 작성
vote.py
길기도 하다!!
마찬가지로 question = get_object_or_404(Question, pk=question_id)를 통해 choice_set 속성에 든 항목들을 가져온다.
Choice모델을 검색하는데(question.choice_set.get) 그 조건을 pk=request.POST['choice']로 삼은 것!
만약 choice라는 key가 없으면 Keterror를 발생시킨다. 또한 조건에 맞는 객체가 없으면 Choice.DoesNotExist를 발생.
그리고 이러한 에러가 발생하면 다시 detail.html을 render한다.
이때 You didn't select a choice라는 에러메시지도 함께 html상에 뿌려준다.
그리고 이것이 아까전에 지나간 error_message!
에러가 발생하지 않았을 때, 즉 정상적으로 처리됬을 때는 해당 함수를 작동시킨다.
selected_choice의 votes에 하나를 더해주고, .save로 저장!
마지막으로 HttpResponseRedirect를 통해 결과를 반환한다. 왜?
POST 방식의 form 데이터를 처리하는 경우,
그 결과를 보여줄 페이지로 이동시키기 위해서는 HttpResponseRedirect객체를 return하는 것이 일반적...이라고 한다.
그리고 이러한 HttpResponseRedirect 객체는 redirect할 타겟 URL을 인자로 받는데, 이는 reverse()함수로 만든다.
reverse()함수는 또 뭔디?
일반적으로 URL 스트링과 뷰를 매핑한 각 라인을 URL 패턴이라 하고 이름을 하나씩 부여한다.
그런데 이 반대 방향, 즉 URL 패턴명으로부터 URL 스트링을 구할 수 있는데 이것이 바로 reverse()함수.
함수의 인자로 reverse(URL 패턴명, URL 스트링에 사용될 파라미터) 를 받는다.
즉 간단히 말하자면 일반적으로 우리는
/polls/<question_id>/results/라는 url을 통해 views.result()를 작동시킨다.
하지만 reverse함수를 통해서는
reverse('polls.results', args=(question.id))로 /polls/<question_id>/results를 추출하는 것!
이렇게 적으니 뭔가 간단하다
4) results 함수 & results.html
마지막으로 투표 결과를 보여주는 results 함수와 html을 작성.
views.py
마찬가지로 question를 받아 results.html에 뿌려주자!
results.html
{% for choice in question.choice_set.all %} -> 아까랑 똑같다!
'설문항목' - '득표 수' vote(s) 형태로 띄워줘야 한다!
즉 {{choice.choice_text}}와 {{choice.votes}}를 통해 각 choice별 choice_text와 votes를 받아온다.
{{choice.votes|pluralize}}는 choice.votes 값에 따라 복수 접미사 s를 붙여주는 역할.
여기까지 잘 따라왔다면, 해당 페이지는 다음과 같다.
이상 Polls 애플리케이션 완성!
'source-code > Django' 카테고리의 다른 글
Books App _ log 만들기 (0) | 2020.12.30 |
---|---|
Books App _ home 만들기 (0) | 2020.12.30 |
Books App _ Template 상속하기 (0) | 2020.12.30 |
Books App (0) | 2020.12.29 |
자잘자잘 문제들 (0) | 2020.11.03 |