form
์ ์ด์ฉํ์ฌ ํด๋ผ์ด์ธํธ์ธ ์ฌ์ฉ์๋ก๋ถํฐ ์๋ฒ์ชฝ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๋ ๋ฐฉ๋ฒ์ ์์๋ณด๋ ค๊ณ ํ๋ค.
์ ๋ฒ part3์์ ๋ง๋ ๋ทฐ๋ ํจ์๊ธฐ๋ฐ์ด์๋ค.
์ด๋ฒ์๋ class
๊ธฐ๋ฐ์ผ๋ก ๋ทฐ๋ฅผ ๋ง๋ค์ด๋ณด๋ ค๊ณ ํ๋ค.
class๊ธฐ๋ฐ ๋ทฐ๋ก ๊ตฌํํ๋ฉด ์์ค์ฝ๋๊ฐ ์ค์ด๋ ๋ค๋ ์ฅ์ ์ด ์๋ค.
form
๋ง๋ค๊ธฐpolls/detail.html
ํ์ผ์ ์์ ํ์ฌ, ํ
ํ๋ฆฟ์ 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>
์ฝ๋๋ฅผ ์ดํด๋ณด์๋ฉด,
๋ฐ์ดํฐ๋ฅผ ์ ์ก์ ์ํ ์์ฒญ๋ฐฉ์์ post
๋ฐฉ์์ผ๋ก ํ๊ธฐ ์ํด post
๋ฅผ ๋ช
์ํด์ฃผ์๋ค.
์ฌ์ฉ์๊ฐ ์๋ฒ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด์ฃผ๊ธฐ ์ํ์ฌ form
ํ๊ทธ์ input
ํ๊ทธ๋ฅผ ์ฌ์ฉํ์๋ค.
์ฌ์ฉ์๊ฐ submit type
์ input tag
์ ๋๋ฅด๋ฉด ํด๋น url์ธ polls:vote
๋ก ๋ฐ์ดํฐ๊ฐ ์ ๋ฌ๋๊ณ , ํด๋น url์ ์ฐ๊ฒฐ๋์ด ์๋ ๋ทฐ์ธ views.vote
๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌ๋ฅผ ํ๊ฒ ๋๋ค.
์ด๋ ๋ทฐ๋ก ์ ๋ฌ๋๋ ๋ฐ์ดํฐ๋ value
๊ฐ์ด๋ค.
์ฌ๊ธฐ์ ํด๋น์ฝ๋๊ฐ ์ฌ์ฉ๋๋ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ๋ค
{% csrf_token %}
: ์ฌ์ดํธ ์์กฐ์์ฒญ์ผ๋ก, ํดํน๋ฐฉ์ง๋ฅผ ์ํด ์ฌ์ฉํ๋ค.์ฐ๋ฆฌ๋ ์ด๋ฏธ polls
์ฑ์ ์ํด ์๋์ ๋์์๋ ์ฝ๋๋ฅผ ํฌํจํ๋ URLconf
๋ฅผ ๋ง๋ค์ด ๋์๋ค.
- polls/urls.py
path('<int:question_id>/vote/', views.vote, name='vote'),
๋ํ ๊ฐ์์ผ๋ก ๋ง๋ค์ด ๋์๋ vote()
ํจ์๋ฅผ
์ค์ ๋ก ๊ตฌํ ํ๊ธฐ ์ํด ๋ค์๊ณผ ๊ฐ์ด ์์ ํด์ค๋ค.
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,)))
๋ค์ ์ฝ๋๋ฅผ ํด์ํด๋ณด์๋ฉด,
def vote(request, question_id)
: vote
๋ทฐ๋ฅผ ํธ์ถํ ๋ question_id
๋ฅผ ๋๊ฒจ ๋ฐ์question = get_object_or_404(Question, pk=question_id)
: question_id
๋ฅผ ๋๊ฒจ ๋ฐ์ผ๋ฉด question๋ฐ์ดํฐ๋ฅผ ์กฐํexcept (KeyError, Choice.DoesNotExist):
: ์กฐํํ์ ๋ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด ์์ธ๊ฐ ๋ฐ์return render(request, 'polls/detail.html', { 'question': question, 'error_message': "You didn't select a choice.", })
: ์์ธ๊ฐ ๋ฐ์ํ์ ๋ ๋ค์ detail.html
(์์ธํ์ด์ง)๋ก respose
๋ฅผ ํด์ฃผ๋ฉฐ, context
๋ฐ์ดํฐ๋ก question
๊ณผ error_message
๋ฅผ ๋ณด๋ด์ค else: selected_choice.votes += 1 selected_choice.save()
: ์กฐํํ์ ๋ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด choice๋ฅผ 1 ์ฌ๋ ค์ฃผ๊ณ ์ ์ฅreturn HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
: reverse
ํจ์๋ฅผ ํตํด results
๋ทฐ๋ฅผ ํธ์ถ.reverse
๋ ๋ทฐ ํจ์์์ url
์ ํ๋์ฝ๋ฉํ์ง ์๋๋ก ๋์์ค์์ ํ ์๋ฒ๋ฅผ ํ์ธํด๋ณด๋ฉด ๋ง๋ค์ด์ค form
์ ํ์ธ ํ ์ ์๋ค.
results
๋ทฐ ๋ง๋ค๊ธฐ์ฌ์ฉ์๊ฐ ์ค๋ฌธ์กฐ์ฌ์ ์ค๋ฌธ์ ํ๊ณ ๋๋ฉด, vote
๋ทฐ๋ ์ค๋ฌธ์กฐ์ฌ ๊ฒฐ๊ณผ ํ์ด์งresult
๋ฅผ ํธ์ถํ๋ค.
๋ฐ๋ผ์ result
๋ทฐ๋ฅผ ์์ฑํด๋ณด๋ ค๊ณ ํ๋ค.
- polls/view.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})
results
๋ทฐ๋ question
์ ์กฐํํ ๋ค์, results.html
์ ๊ฒฐ๊ณผํ์ด์ง๋ก ๋ณด์ฌ์ค๋ค.
์ด๋ 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>
๋ทฐ๋ก๋ถํฐ question
๋ฐ์ดํฐ๋ฅผ ๋ฐ์์,
question_text
๊ฐ ์ ๋ชฉ์ด ๋๊ณ
question์ ๋ํ ์ ํ์ง(choice)
๊ฐ๋ค์ด ๋ฐ๋ณต๋ฌธ์ ๋๋ฉฐ ๋ฆฌ์คํธ๋ก ๋ค์ด๊ฐ๋ค.
์ฌ๊ธฐ์ ์ฒ์๋ณด๋ ํค์๋์ ๋ํด ์์๋ณด์๋ฉด,
vote{{ choice.votes|pluralize }}
: pluralize
๋ votes
๊ฐ ๋จ์์ธ ๊ฒฝ์ฐ๋ ๋จ์์ฒ๋ฆฌ๋ฅผ, ๋ณต์์ธ ๊ฒฝ์ฐ๋ ๋ณต์์ฒ๋ฆฌ๋ฅผ ํ๋ ์ฅ๊ณ ์์ ์ ๊ณตํ๋ ํ
ํ๋ฆฟ ๊ธฐ๋ฅ์ด๋ค.์์ ๊ฐ์ด ์ฒ์๋ณด๋ ํค์๋๊ฐ ์๋ค๋ฉด ์ธ์ฐ๋ ๊ฒ์ด ์๋๋ผ ํค์๋์ ๋ํด ๊ตฌ๊ธ๋ง ํด์ ์ฐพ์๋ณด๋ฉด ๋๋ค
์ด์ ์๋ฒ์์ ์ค๋ฌธ์ ๋ํ ํฌํ๋ฅผ ํ๊ณ ๋๋ฉด, ๊ฒฐ๊ณผํ์ด์ง(results)
๋ฅผ ํ์ธํ ์ ์๋ค.
generic
๋ทฐ ์ฌ์ฉํ๊ธฐclass
๊ธฐ๋ฐ์ ๋ทฐ๋ฅผ generic
๋ทฐ๋ผ๊ณ ๋ ํ๋ค.
generic
๋ทฐ๋ ์ผ๋ฐ์ ์ธ ํจํด๋ค์ ๋ํด ์ฅ๊ณ ์์ ๋ง๋ค์ด๋์๊ธฐ ๋๋ฌธ์ ํจ์ํ ๊ธฐ๋ฐ ๋ทฐ์ ๋นํด ์ฝ๋๋์ด ์ ๋ค.
generic
๋ทฐ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด url
๊ณผ views
์ฝ๋๋ฅผ ์์ ํด์ค๋ค.
- polls/url.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'),
]
generic
๋ทฐ๋ ์ฅ๊ณ ์์ ๋ฏธ๋ฆฌ ์์ฑ ๋ as_view
ํจ์๋ฅผ ํธ์ถํ์ฌ ๋ทฐ๋ฅผ ํธ์ถํ๊ฒ ๋๋ค.
์ด๋ detail
์ด๋ results
url
์์๋ int:question_id
๋ผ๋ ํ๋ผ๋ฏธํฐ ์ด๋ฆ์ ์ง์ฐ๊ณ pk
๋ง ๋ช
์ํด์ฃผ๋ฉด ๋๋ค.
์ฌ๊ธฐ์ pk
๋ db๋ด์ ํ๋์ ์ด, ์ฆ ํ๋์ ๋ฐ์ดํฐ๋ฅผ ๊ตฌ๋ถํ ์ ์๋ ๊ฐ์ด๋ค. pk
๊ฐ์ ์ค๋ณต๋์ง ์๋๋ค
- 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.
์ด๋ ๊ฒ generic
๋ทฐ์์๋
์ฌ์ฉํ ํ
ํ๋ฆฟ ์ด๋ฆ, ํด๋น ํ
ํ๋ฆฟ์์ ์ฌ์ฉํ ๋ฐ์ดํฐ ๋ชจ๋ธ์ ๋ช
์ํด์ฃผ๊ธฐ๋ง ํ๋ฉด ๋๋ค.
์ด๋ context
์ ๋๊ฒจ์ฃผ๋ ๋ฐ์ดํฐ์ ์ด๋ฆ์ด ๋ชจ๋ธ์ด๋ฆ๊ณผ ๋ค๋ฅด๋ค๋ฉด context_object_name
์ ๋ค์ ์ ํด์ฃผ๊ณ ,
ํ์ํ ๋ฐ์ดํฐ๋ฅผ get_queryset
ํจ์๋ฅผ ์ด์ฉํด์ ๋ค์ ์์ฑํด์ฃผ๋ฉด ๋๋ค.
generic
๋ทฐ๋ ์ ํํ๋ ์์
๋ค์ด ์ด๋ฏธ ๋ง๋ค์ด์ ธ ์์ด ๊ธฐ๋ฅ๋ค์ ์ตํ ๊ฐํธํ๊ฒ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ด๋ค.
ํ์ง๋ง ์ฅ๊ณ ์ ์ต์ํด์ง๋ ๊น์ง๋ ํจ์ ๊ธฐ๋ฐ ๋ทฐ๋ฅผ ์์ฑํ๋ ๊ฒ์ ์ถ์ฒํ๋ค!
๐ ์ฐธ๊ณ
๋์ฅ๊ณ ๊ณต์๋ฌธ์
๋์ฅ๊ณ ๊ณต์๋ฌธ์ ๊ฐ์์๋ฃ