본문 바로가기

프로그래밍/python django

투표 어플리케이션을 통해 django 이해하기-2

이제 Django를 통해 다양한 투표 기능을 만들어볼 것이다. 저번까지 간단하게 전체 투표 화면을 만들어보았다.


 Choice 보기

이제 각 투표 주제를 누르면 세부적인 질문이 나오는 기능을 구현해볼 것 이다.

우선 views.py에 기능을 정의해준다.


from django.shortcuts import render, get_object_or_404
#맨 윗줄에 get_object_or_404를 사용하기위해 추가한다.
#이전에 get_object_all은 모든 객체를 불러와 저장시키는 것이었다.
#get_object_or_404는 특정 조건의 객체를 불러오는데 사용하며, 만약 만족하는 객체가 없다면 404 에러가 뜨게된다.
def detail(request, qid):
    b=get_object_or_404(Question, id=qid)
#id=qid의 조건을 만족하는 객체를 불러오라는 뜻이다.
    return render(request, 'vote/detail.html',{'q':b})
#불러온 객체를 q라는 변수로 detail.html로 보낸다는 뜻이다.

보낸 객체변수를 받기위해 detail.html을 작성해보자.



<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<h1>{{q.name}}</h1> 
<p>{{q.date}}</p>
<form>
{% for c in q.choice_set.all %} 
#view에서 id=qid를 만족하는 Question객체를 변수 q로 보냈다.
#q.choice_set.all은 Question 객채 q와 연결된 choice객체의 모든 것을 받아오겠다는 뜻
<input type="radio" name="a" value="{{c.id}}"> #c.id를 value로 주고
<label>{{c.name}}</label> #c.name으로 label을 준다
<br>
{% endfor %}
<input type="submit" value="투표하기">
</form>

</body>
</html>


마지막으로 url을 통해 해당 함수를 불러와보자



urlpatterns = [
    path('', index),
    path('<int:qid>',detail),
#int:qid는 숫자 1,2,3을 의미한다. 앞서 만든 detail함수가 받는 매개변수 qid를 url에서 지정해준다. 

    ]


실제로 해당 기능을 끝내고 다음과 같은 url를 입력하면 기능이 구현된 것을 확인할 수 있다.

vote다음에 1, 2, 3을 입력할 시 각각 질문이 바뀌는 것을 확인가능하다.


여기서 id에 대한 조금 더 부가설명을 하겠다.

우리가 Question을 만들때 name과 date만 만들어줬지만 사실 기본으로 id라는 변수 또한 추가된다.

이 id는 기본키로 각 데이터를 구분할 수 있는 고유값이라고 생각하면된다.

이것을 url에서 id값이 붙으면 detail함수가 실행되도록 명시해줬다. 이때 id 값이 qid이다.

qid는 detail 함수로 넘어가서 id를 기준으로 Question 객체를 불러오며 이것을 q라는 객체에 저장한다.

받은 q를 html에로 넘어가서 각 받은 q값의 id에 맞는 Choice 객체를 불러오며 이것이 q.choice_set.all이다.


지금까지 우리는 url을 통해 각 홈페이지를 이동했다. 그러나 일반적으로 우리는 url을 통해 이동하지않는다.

보통 우리는 하이퍼링크를 통해 이동한다. Django는 이런 하이퍼링크를 쉽게 이용할 수 있도록 해준다.

우선 urls.py에 다음과 같은 코드를 추가해주자.



urlpatterns = [

    path('', index, name='index'),

    path('<int:qid>',detail, name='detail'),

    ]

해당 코드를 추가 시 html에서 이름으로 url을 사용이 가능하다.



<tr>

<td>{{q.id}}</td> {# 단순히 값을 표한하고 싶다면 {{ }} 을 사용한다.#}

<td><a href="{% url 'vote:detail' q.id %}">{{q.name}}</a></td>

#클릭 시 detail.html로 넘어간다.

<td>{{q.date}}</td>

</tr>

또한  detail.html에도 다음과 같은 식을 추가해준다.


투표하기/결과보기

투표하기와 결과보기 기능도 이와 비슷하게 구현해주면 된다.


우선 view를 통해 기능 정의부터 해준다.




from django.http.response import HttpResponseRedirect
from django.urls import reverse
def vote(request):

    if request.method == "POST": #요청 방식이 POST인지 확인
    
        c_id = request.POST.get('a') 
        c = get_object_or_404(Choice, id = c_id) 
#POST방식으로 넘어온 데이터 중 입력한 키값과 동일한 데이터를 추출
        c.votes += 1  #투표수 증가
       c.save() #변동사항 DB에 저장
       return HttpResponseRedirect( reverse('vote:result',args=(c.q.id ,)  ) )
#HttpResponseRedirect, reverser를 사용 시 자동으로 다른 페이지로 넘겨주는 역할을 함
#c.q.id는 Choice객체 q와 연결된 Question 객체 q의 id값을 의미함

#result(투표 결과)
def result(request, q_id):
    
    return render(request, 'vote/result.html', 
                  {'q' : get_object_or_404(Question, id = q_id) } )



이제 result.html을 작성해주자.


<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>Insert title here</title>

</head>

<body>

<h1>{{q.name}} 투표결과</h1>

<ul>

{% for c in q.choice_set.all %}

<li> {{c.name}} - {{c.votes}} 표 </li>

{% endfor %}

</ul>

<a href="{% url 'vote:index' %}">메인페이지로 돌아가기</a>

</body>

</html>


마지막으로 url을 작성해준다.


urlpatterns = [

    path('', index, name='index'),

    path('<int:qid>',detail, name='detail'),

    path('vote/', vote, name='vote'),

    path('result/<int:q_id>/', result, name="result"),

    ]


이제 유동적인 홈페이지 하나가 완성된 것을 확인 가능하다.