티스토리 뷰

study/Django

Django tutorial 따라하기 4

xoxowo 2022. 6. 30. 22:44

튜토리얼 4에서는 polls(투표 앱) 애플리케이션의 간단한 폼 처리와 소스코드를 줄이는데 중점을 둔다. 

+ 장고에서 지원하는 generic views 시스템을 같이 알아본다.

 

 

간단한 폼 쓰기

튜토리얼 3에 작성한 투표 상세 템플릿(polls/detail.html) 템플릿에 <from> 요소를 포함시켜 보자.

<form action="{% url 'polls:vote' question.id %}" method="post">
// 사이트 위조, 해킹방지를 위해 {% csrf_token %} <- token 코드 삽입
{% csrf_token %}
<fieldset>
    <legend><h1>{{ question.question_text }}</h1></legend>
    {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
    {% for choice in question.choice_set.all %}
        <input type="radio" name="choice" id="choice{{ forloop.counter }}" 
        value="{{ choice.id }}">
        
        // forloop.counter는 for 태그가 반복한 횟수를 나타낸다
        <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
    {% endfor %}
</fieldset>
<input type="submit" value="Vote">
</form>

내부 코드 살펴보기 

하드코딩 된 url 주소도 수정했고 method도  'post' 방식으로 설정하였다. 이 method ="post"방식을 사용하는 것은 중요하다고 한다.

input 태그를 살펴보면 name이 choice인 것이 보이는데, 클라이언트가 라디오 버튼 중 하나를 선택하여 제출(vote)하면 POST 데이터인 choice= #을 보낸다. (#는 선택한 항목의 id이다.)

 

또 내부 URL을 대상으로 하는 모든 'POST' 양식은 교차 사이트 요청 위조에 대해 보호하기 위해 {% csrf_token %} 템플릿 태그를 사용해야 한다고한다.

외부 화면 살펴보기

화면을 새로고침 하면 기존의 <li> 태그로 출력됐던 {{ choice.choice_text }} 태그가 radio 타입의 <input> 태그로 바뀌었으며 이 데이터 정보를 보내는 submit 버튼도 생긴 것을 볼 수 있다.

 

vote() 함수를 가상으로 만들었었는데, polls/view.py파일에 실제로 구현하도록 코드를 입력해보자.

def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        # Redisplay the question voting form.
        return render(request, 'polls/detail.html', {
            'question': question,
            'error_message': "You didn't select a choice.",
        })
    else:
        selected_choice.votes += 1
        selected_choice.save()
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

여기서 중요한 부분은 selected_choice = qeustion.choiceset.get(pk=request.POST ['choice'])인데,

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

위 경우에는 request.POST ['choice']는 선택된 질문의 ID를 문자열로 반환하는데, request.POST ['choice']의 값은 항상 문자열이라고 한다.

튜토리얼의 경우 form 태그의 매소드 방식이 'post'이기 때문에 post 요청을 통해서만 자료가 수정되게 하기 위해 request.POST를 사용한다고 한다.

 

 

 

 

투표 결과 화면 뷰 작성

Question(질문)에 대해 여러 개의 choice 리스트가 생성되고, 클라이언트가 이 choice 리스트 중에 어느 하나 값을 골라 투표를 하면 투표 결과가 나오는 뷰(view)를 만들어야 한다.

 

이전에 polls/view.py에 추가한 코드는 설문조사 결과 페이지로 리다이렉트 하는 코드이다.

def results(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/results.html', {'question': question})

구현 후 화면을 클라이언트에게 보여주기 위해 polls/results.html 템플릿을 만들어 내부 코드를 작성한다.

for 문으로 투표(vote) 결과 값이 나오고 투표하는 화면으로 돌어가는 <a> 태그도 확인할 수 있다.

<h1>{{ question.question_text }}</h1>

<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>

<a href="{% url 'polls:detail' question.id %}">Vote again?</a>

 

 

 

 

 

 

 

 

 

 


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

우리가 튜토리얼에서 만든 view들은 매우 간단하며 거의 비슷비슷하다. url에 전달된 매개 변수에 따라 DB에서 데이터를 가져오고 템플릿을 로드하고, 템플릿을 클라이언트에게 반환하는 아주 일반적인 경우가 흔하기 때문에 장고는 '제네릭 뷰' 시스템이라고 불리는 단축키를 제공한다.

 

장고 튜토리얼 전문에 나와있는 내용을 발췌해왔는데 아래대로 실행해보도록 하겠다.

 

제너릭 뷰는 일반적인 패턴을 추상화하여 앱을 작성하기 위해 Python 코드를 작성하지 않아도 됩니다.

우리 설문조사 애플리케이션을 제너릭 뷰 시스템으로 변환해서 우리의 코드를 많이 삭제하도록 합시다. 이러한 전환을 하려면 다음과 같은 몇 가지 단계만 거치면 됩니다:

  1. URLconf를 변환하십시오.
  2. 불필요한 오래된 보기 중 일부를 삭제하십시오.
  3. Django의 제너릭 뷰를 기반으로 새로운 뷰를 도입하십시오.

 

1. URLconf 수정(변환)

기존에 작성했던 polls/urls.py의 URLconf를 변경하자.

 

두 번째와 세 번째 패턴의 경로 문자열에서 일치하는 패턴들의 이름이 <question_id>에서<pk>로 변경되었다.

 

수정 전)                                                                                             수정 후)

views 수정

마찬가지로 이전에 작성했었던 index, detail, results view를 제네릭뷰로 바꿔보자.

 

수정 전)                                                                                             수정 후)

 

 

수정한 코드를 살펴보면 코드가 좀 더 간결해졌다. 

 

model은 각 제네릭 뷰가 어떤 모델이 적용될 것인지를 알게 하는 것인데 class DetailView와 class ResultsView는 동일한 매개변수(generic.DetailView)를 가지고있는데 template_name을 지정해서 페이지를 각 각 다른 페이지로 연결될 수 있도록 장고에게 알려준다.

 

해당 코드에 대한 자세한 내용은 장고 튜토리얼 페이지에서 확인하도록 하자!

 


내용 전문 및 출처 -djangoproject

 

 

 

 

 

'study > Django' 카테고리의 다른 글

Django - MtoM Field 없이 구현  (0) 2022.07.06
westarbucks 만들기 - models.py  (0) 2022.07.05
Django tutorial 따라하기 3  (0) 2022.06.29
Django tutorial 따라하기 2  (0) 2022.06.29
Django tutorial 따라하기 1  (0) 2022.06.28
댓글