본문 바로가기

Django 맛보기

Django 맛보기6 - 심화된 뷰(View) 만들기

안녕하세요 개발자정씨입니다.

꽤 오랫만에 돌아온것 같네요 언능 시작해보죠

 

1. 투표 form 만들기

# polls/templates/polls/detail.html

<form action="{% url 'polls:vote' question.id %}" method="post">
{% 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 }}">
        <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
    {% endfor %}
</fieldset>
<input type="submit" value="Vote">
</form>

polls/templates/polls/detail.html를 위와 같이 수정하여 form을 만들어주고

 

# polls/views.py

from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse

from .models import Choice, Question
# ...
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,)))

polls/views.py를 위와 같이 수정하여 투표기능으로 동작하게끔 만들어줍니다.

 

# polls/views.py

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

그리고 results 함수를 위와같이 변경하여 results.html를 render할 수 있도록 해줍니다.

 

# polls/templates/polls/results.html

<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>

그리고 result.html까지 마무리!

 

완성하고 나면 위와 같이 투표항목 선택 > 투표 > 투표결과까지 정상적으로 동작하는 것을 확인 할 수 있습니다.

대세의 3분할

 

* 참고. 혹시 질문의 답변이 보이지 않는 분들은 https://docs.djangoproject.com/ko/3.2/intro/tutorial02"API 가지고 놀기"를 참고해주세요

 

 

2. 제너릭 뷰 사용하기

제가 참고하고 있는 Docs에서 제너릭 뷰를 아래와 같이 설명하고 있습니다.

 

"이전에 보였던 것 처럼 뷰는 URL에서 전달 된 매개 변수에 따라 데이터베이스에서 데이터를 가져 오는 것과 템플릿을 로드하고 렌더링 된 템플릿을 리턴하는 기본 웹 개발의 일반적인 경우를 나타냅니다. Django는 이런 매우 일반적인 경우를 위해 《제너릭 뷰》시스템이라는 지름길을 제공합니다."

 

어떻게 쓰는건지 아래에서 확인해보시죠

 

# polls/urls.py

from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

polls/urls를 위와 같이 수정해주세요

 

# polls/views.py

from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic

from .models import Choice, Question


class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        """Return the last five published questions."""
        return Question.objects.order_by('-pub_date')[:5]


class DetailView(generic.DetailView):
    model = Question
    template_name = 'polls/detail.html'


class ResultsView(generic.DetailView):
    model = Question
    template_name = 'polls/results.html'


def vote(request, question_id):
    ... # same as above, no changes needed.

그리고 polls/veiws.py를 위와 같이 수정해주세요.

수정을 마치고 나서도 동일한 기능을 정상적으로 수행하는 것을 확인 할 수 있습니다.

 

 

자세한 내용은 저도 조금 더 훑어봐야할 것 같습니다.

이해가 잘 안되는 부분은 댓글을 통해서 서로 의견 나눌 수 있으면 좋겠습니다.

항상 감사드립니다.