튜토리얼 4에서는 form을 통한 입력을 받는 방식과, generic view 사용법을 배울 수 있습니다.
제네릭 뷰를 상속 받아 화면에 view를 작성한다면 코드에 양을 줄이 실 수 있습니다.
form을 사용하고 선거 앱을 완성해보자.
polls/templates/polls/detail.html
<h1>{{ question.question_text }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% 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 %}
<input type="submit" value="Vote">
</form>
각각의 질문 선택을 위해서 질문과 라디오 버튼을 보여줍니다.
post 방식에서 Cross Site Request Forgeries을 막아주기 위해서 django는 간단한 해결책을 제공합니다.
{% csrf token %}을 명시함으로써 Cross Site Request Forgeries을 막을 수 있습니다.
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,)))
post data를 처리 한 이후에는 HttpResponseRedirect를 리턴해줍니다. 이유는 유저가 뒤로가기 버튼 이후에 두번 제출되어지는 걸 막기 위해서 HttpResponseRedirecct를 이용해줍니다.
다음으로는 results가 호출 되어지는데 다음 코드를 작성해 봅시다.
polls/views.py
from django.shortcuts import get_object_or_404, render
def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question': question})
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>
제네릭 뷰를 사용해보자.
detail, result views 는 화면에 보여주는 뷰들이다. 웹 어플리케이션의 기본적인 기능이 있다. 바로 화면에 보여주는 내용인데 django는이런 내용들을 클래스로 이미 만들어져 있기 때문에 이미 만들어져 있는 클래스들(제네릭 뷰)을 이용한다면 코드의 양을 줄일 수 있다.
(처음에 연습할 때는 제네릭 뷰를 이용하지 말고 지금까지의 방법들로 코드들을 작성하자. 그리고 이후에 제네릭 뷰를 적용시켜보자.)
위와 같은 코드들을 제네릭 뷰로 변경 해보자.
1. url 코드를 변경한다.
2. 사용하지 않는 view코드를 삭제한다.
3. 제네릭 기반의 새로운 view를 작성한다.
1. url코드를 변경한다.
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'),
]
2/3. views.py를 수정하자
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.
2가지 제네릭 뷰를 이용하였다. ListView와 DetailView를 이용하였는데 각각의 특징을 알아보자.
ListView : 리스트를 보여줘라.
DetailView : 상세 페이지를 보여줘라.
제네릭뷰는 사용하는 모델을 알아야된다. 또한 기본적으로 키값을 이용한 데이터를 보여주기 때문에 urls.py내용도 pk로 변경해준다.
'Programming > python' 카테고리의 다른 글
[python] django 튜토리얼 part 6, about static file (0) | 2019.01.04 |
---|---|
[python] django 튜토리얼 part 5, about automated testing (0) | 2019.01.02 |
[python] django 튜토리얼 part 3, about template (0) | 2018.12.23 |
[python] django 튜토리얼 part 2, about db, model and admin (0) | 2018.12.21 |
[python] django 튜토리얼 part 1, about setting (0) | 2018.12.17 |