10 Sun

TIL

[๋ฐฐํ”„์˜ ์˜ค์ง€๋ž– ํŒŒ์ด์ฌ ์›นํ”„๋กœ๊ทธ๋ž˜๋ฐ]

3 ํŠœํ† ๋ฆฌ์–ผ ๋”ฐ๋ผํ•˜๊ธฐ - ์„ค๋ฌธ์กฐ์‚ฌ

3.10 404 ์˜ค๋ฅ˜ ์ผ์œผํ‚ค๊ธฐ

404์˜ค๋ฅ˜๋Š” ์›น ์„œ๋น„์Šค์—์„œ ํŒŒ์ผ์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜์ด๋‹ค. ๊ฒŒ์‹œํŒ์—์„œ ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ ์˜ฌ ๋•Œ ํŽ˜์ด์ง€์— ํ•ด๋‹น ๋ฐ์ดํ„ฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์˜๋ฏธ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

polls/views.py

from django.http import Http404
def detail(request, question_id):
    try:
        question = Question.Objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
    return render(request, 'polls/detail.html', {'question': question})

Http404๋ฅผ ์ด์šฉํ•˜๋ฉด ํˆฌํ‘œ ํ•ญ๋ชฉ์ด ์—†์„ ๊ฒฝ์šฐ 404 ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. ์ด์ „์˜ index๋ทฐ์™€ ๊ฐ™์ด detail ๋ทฐ์—์„œ ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ detail.html์„ ์ƒ์„ฑํ•œ๋‹ค.

Http404๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ๋Š” loade-rrender ๊ด€๊ณ„์ฒ˜๋Ÿผ ๋‹จ์ถ• ํ•จ์ˆ˜๊ฐ€ ์กด์žฌํ•˜๋Š”๋ฐ get_object_or_404 ์ด๋‹ค. ์ด ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด detail ๋ทฐ๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค.

polls/views.py

from django.shortcuts import get_object_or_404
def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})

render์˜†์— get_object or 404๋ฅผ ์ถ”๊ฐ€ํ•ด ์ž„ํฌํŠธ ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  detail ๋ทฐ์—์„œ๋Š” try except ๊ตฌ๋ฌธ์„ ์—†์• ๊ณ  404๋ฅผ ์ด์šฉํ•ด ์ฝ”๋“œ๋ฅผ ๊ฐ„์†Œํ™” ํ•œ๋‹ค. ์ด๋ฅผ detail.html ์— ์ถ”๊ฐ€ํ•œ๋‹ค.

polls/templates/polls/detail.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>{{ question.question_text }}</h1>
    <ul>
    {% for choice in question.choice_set.all %}
        <li> {{ choice.choice_text }} </li>
    {% endfor %}
    </ul>
</body>
</html>

3.11 ํ•˜๋“œ ์ฝ”๋”ฉ๋œ URL ์—†์• ๊ธฐ

index.html ํŒŒ์ผ์„ ๋ณด๋ฉด ๋งํฌ์˜ ์ฃผ์†Œ๊ฐ€ ํ•˜๋“œ์ฝ”๋”ฉ ๋˜์–ด์žˆ๋‹ค. ์ด๋Š” ๋‹ค๋ฅธ ํ˜•ํƒœ๋กœ ๋ณ€๊ฒฝ์‹œ ์ผ์ผ์ด html์„ ๋‹ค ์—ด์–ด์•ผ ํ•œ๋‹ค๋Š” ๋ถˆํŽธํ•จ์ด ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ URL ํ…œํ”Œ๋ฆฟ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•˜๋“œ ์ฝ”๋”ฉ๋œ URL์„ ์—†์•ค๋‹ค.

{% for question in latest_question_list %}
        <li><a href={% url 'detail' question.id %}>{{ question.question_text }}</a></li>
{% endfor %}

URL ํ…œํ”Œ๋ฆฟ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•ด ์ฃผ์†Œ๋ฅผ ๋งŒ๋“ค์–ด ์ถœ๋ ฅํ•œ๋‹ค. URL ํ…œํ”Œ๋ฆฟ ํƒœ๊ทธ๋Š” URL์˜ ์ด๋ฆ„์„ ํ•„์ˆ˜ ์ธ์ž๋กœ ์ „๋‹ฌ ๋ฐ›๋Š”๋‹ค. ํ•ด๋‹น ์ด๋ฆ„์„ ๊ฐ€์ง„ URL์€ ulrs.py ์ „์ฒด๋ฅผ ๊ฒ€์ƒ‰ํ•ด ์ฐพ๋Š”๋‹ค.

3.12 URL ๋„ค์ž„ ์ŠคํŽ˜์ด์Šค ์„ค์ •ํ•˜๊ธฐ

detail์ด๋ผ๋Š” ๋ทฐ๊ฐ€ polls์—๋„ ์žˆ๊ณ  ๋‹ค๋ฅธ ์•ฑ์—๋„ ์žˆ์„ ๊ฒฝ์šฐ ์žฅ๊ณ ๋Š” ์–ด๋А ๋ทฐ์˜ URL์„ ๋งŒ๋“ค์ง€ ์•Œ ์ˆ˜๊ฐ€ ์—†๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ์„ค์ •ํ•ด ๊ฐ๊ฐ์˜ ๋ทฐ๊ฐ€ ์–ด๋А ์•ฑ์— ์†ํ•œ ๊ฒƒ์ธ์ง€ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค. ํ”„๋กœ์ ํŠธ๊ฐ€ ๋ณต์žกํ•ด์งˆ์ˆ˜๋ก ์žˆ๋Š” ๊ฒƒ์ด ํŽธ๋ฆฌํ•˜๋‹ค.

polls/urls.py

app_nmae = 'polls'

polls/template/polls/index.html

{% for question in latest_question_list %}
        <li><a href={% url 'polls:detail' question.id %}>{{ question.question_text }}</a></li>
{% endfor %}

3.13 ๊ฐ„๋‹จํ•œ ํผ ์ œ์ž‘

ํŠœํ‘œ ๊ธฐ๋Šฅ์ด ๋™์ž‘ํ•˜๋ ค๋ฉด detail.html์„ ์ˆ˜์ •ํ•˜๊ณ  vote ๋ทฐ์—๋„ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.

detail.html

<body>
    <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>
    
    </ul>
</body>
  • form ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ต๋ณ€ ํ•ญ๋ชฉ์„ ์„ ํƒํ•˜๊ณ  ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ํ•ญ๋ชฉ์˜ ๋ฒˆํ˜ธ๋ฅผ vote ๋ทฐ๋ฅผ ์ „๋‹ฌํ•˜๋„๋ก action ์†์„ฑ์— vote URL์ด ์ถœ๋ ฅ๋˜๊ฒŒ URL ํ…œํ”Œ๋ฆฟ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

  • method = post๋Š” HTTP ๋ฉ”์„œ๋“œ ์ค‘ ํ•˜๋‚˜์ด๋ฉฐ ์„œ๋ฒ„๋กœ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•

  • forloop.counter๋Š” ํ…œํ”Œ๋ฆฟ ๋ฌธ๋ฒ•์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์œผ๋กœ ๋ฐ˜๋ณต๋ฌธ์˜ ๋ฐ˜๋ณต ํšŸ์ˆ˜๋ฅผ ์ถœ๋ ฅํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ. ์—ฌ๊ธฐ์„œ๋Š” vote๋ทฐ์— choice=๋ฒˆํ˜ธ ํ˜•ํƒœ๋กœ ์ „๋‹ฌํ•œ๋‹ค

  • csrftoken์€ CSRF ๊ณต๊ฒฉ์„ ๋ง‰๊ธฐ์œ„ํ•œ ์ˆ˜๋‹จ์ด๋‹ค. ๋ฐฉ๊ธˆ ์„œ๋ฒ„๋กœ ๋“ค์–ด์˜จ ์š”์ฒญ์ด ์‚ฌ์ดํŠธ ๋‚ด๋ถ€์—์„œ ์˜จ ๊ฒƒ์ด ๋งž๋Š”์ง€ ํ™•์ธํ•˜๋Š” ์šฉ๋„๋กœ csrftoken์˜ ๊ฐ’์„ ์‚ฌ์šฉ

polls/views.py

from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
from .models import Question, Choice

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):
        return render(request, 'polls/detail.html', {
            'question': question,
            'error_message': "You didn't select a choice.",
        })
    else:
        selected_choice.votes += 1
        selected_choice.save()

        return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
  • request.POST[๋ณ€์ˆ˜์ด๋ฆ„]์„ ํ†ตํ•ด ์ „๋‹ฌ๋ฐ›์€ ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ํ™•์ธํ•œ๋‹ค. ์ด ๋•Œ ์ „๋‹ฌ๋˜๋Š” ๊ฐ’์€ ํ•ญ์ƒ ๋ฌธ์ž์—ด์ด๋‹ค.

  • ์ „๋‹ฌ๋ฐ›์€ ๋‹ต๋ณ€์ด ํ•ด๋‹น ํˆฌํ‘œ ํ•ญ๋ชฉ์— ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์—†์œผ๋ฉด ๋‹ค์‹œ ์ƒ์„ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•œ๋‹ค. ์ด ๋•Œ ๋‹ต๋ณ€์„ ์„ ํƒํ•˜์ง€ ์•Š์•˜๋‹ค๋Š” ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋„ ๊ฐ™์ด ์ „๋‹ฌ๋œ๋‹ค.

  • ๋ฐ˜๋Œ€๋กœ ์ œ๋Œ€๋กœ ๋œ ๋‹ต๋ณ€์ด ์„ ํƒ๋˜๋ฉด ํ•ด๋‹น ๋‹ต๋ณ€ ์ˆ˜๋ฅผ 1 ์ฆ๊ฐ€์‹œํ‚ค๊ณ  ๊ฒฐ๊ณผ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•œ๋‹ค.

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})
  • ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” result๋ทฐ

polls/templates/polls/results.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <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>
</body>
</html>
  • results.html์€ ๊ฐ ๋‹ต๋ณ€ ํ•ญ๋ชฉ๊ณผ ํˆฌํ‘œ ์ˆ˜๋ฅผ ํ•œ๊บผ๋ฒˆ์— ๋ณด์—ฌ์ค€๋‹ค.

3.14 ์ œ๋„ค๋ฆญ ๋ทฐ ์‚ฌ์šฉ

์ œ๋„ค๋ฆญ๋ทฐ๋Š” ์žฅ๊ณ ์—์„œ ๋ฏธ๋ฆฌ ์ค€๋น„ํ•œ ๋ทฐ๋ฅผ ์˜๋ฏธ. ์›น ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋ทฐ๋“ค์€ ์ด๋ฏธ ์žฅ๊ณ ์—์„œ ๋Œ€๋ถ€๋ถ„ ๋งŒ๋“ค์–ด์ ธ ์žˆ๋‹ค.

Last updated

Was this helpful?