JUST DO IT!

[TIL]KDT_20230425 ๋ณธ๋ฌธ

TIL

[TIL]KDT_20230425

sunhokimDev 2023. 4. 25. 17:16

๐Ÿ“š KDT WEEK 4 DAY 2 TIL

  • Django
    • ๋ทฐ(views)์™€ ํ…œํ”Œ๋ฆฟ(templates)
    • ํŽ˜์ด์ง€ ๋งŒ๋“ค๊ธฐ
    • ์—๋Ÿฌ ์ฒ˜๋ฆฌํ•˜๊ธฐ, ๋ฐฉ์–ดํ•˜๊ธฐ
    • ํŽ˜์ด์ง€ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•

 


 

๐ŸŸฅ ๋ทฐ์™€ ํ…œํ”Œ๋ฆฟ

polls/views.py์—์„œ ์šฐ๋ฆฌ๊ฐ€ html์„ ๊ทธ๋ ค์ฃผ๊ธฐ ์œ„ํ•ด render ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•ด๋ณด์ž.

 

from django.http import HttpResponse
from .models import *
from django.shortcuts import render # index.html์„ ๊ทธ๋ ค์ฃผ๋Š” ์—ญํ•  Django ๊ธฐ๋Šฅ

def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'questions' : latest_question_list}
    return render(request, 'polls/index.html', context)

polls/views.py์˜ ์ผ๋ถ€๋ถ„์„ ๊ฐ€์ ธ์™€๋ณด์•˜๋‹ค. 

๊ฐ ํ•ญ๋ชฉ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด๋ณด์ž๋ฉด..

  • latest_question_list์— order_by ๊ธฐ๋Šฅ์œผ๋กœ ์ •๋ ฌํ•˜์—ฌ ๊ฐ€์žฅ ์ตœ๊ทผ ํ•ญ๋ชฉ 5๊ฐœ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
  • context๋Š” ํ…œํ”Œ๋ฆฟ์— ์ „๋‹ฌ๋  ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์•„๊ฐ„๋‹ค. ๋ณด๋‚ด๋Š”๊ฑด render๊ฐ€ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค!
  • render๋Š” Django์˜ ๋‚ด์žฅํ•จ์ˆ˜๋กœ, HTTP ์š”์ฒญ์„ ๋ฐ›์•„ ํ•ด๋‹น ์š”์ฒญ์— ๋Œ€ํ•ด ์›ํ•˜๋Š” ํ…œํ”Œ๋ฆฟ ํŒŒ์ผ์„ ๋ Œ๋”๋งํ•˜์—ฌ ์‘๋‹ตํ•œ๋‹ค.
    • render(์š”์ฒญ , ํ…œํ”Œ๋ฆฟ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ , context๋ฐ์ดํ„ฐ) ์ฒ˜๋Ÿผ ์ฒ˜๋ฆฌํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

์•ž์„œ render์—์„œ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ๋ฅผ 'polls/index.html'๋กœ ์ฒ˜๋ฆฌํ•œ ๊ฒƒ์€,

๋ฏธ๋ฆฌ pollsํด๋”์— templates/polls/index.html ์„ ๋งŒ๋“ค์–ด๋‘์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

์ด์ œ, context๋ฅผ ์ „๋‹ฌ๋ฐ›์€ index.html์—์„œ ํ™”๋ฉด์„ ๊ทธ๋ ค์ฃผ๋Š” ์—ญํ• ์„ ํ•ด์ค„ ๊ฒƒ์ด๋‹ค.

{% if questions %}
<ul>
    {% for question in questions %}
        <li>{{question}}</li>
    {% endfor %}
</ul>
{% else %}
<p>no question</p>
{% endif %}
  • html์—์„œ๋Š” if, for ๋ฌธ์„ ์•ž๋’ค์— {% ์™€ %} ํ˜•ํƒœ๋กœ ์ฒ˜๋ฆฌํ•ด์ค˜์•ผํ•œ๋‹ค.
  • if, for๋ฌธ์ด ๋๋‚˜๋ฉด endif, endfor๊ฐ€ ํ•„์š”ํ•˜๋‹ค!
  • context๋กœ ๋ฐ›์€ questions์˜ ์กด์žฌ์—ฌ๋ถ€์— ๋”ฐ๋ผ ํ™”๋ฉด์˜ ์ถœ๋ ฅ์ด ๋‹ฌ๋ผ์ง€๋Š” ์ฝ”๋“œ์ด๋‹ค.

questions์ด ์กด์žฌํ•  ๋•Œ์˜ ํ™”๋ฉด

 


 

์ƒ์„ธ (detail) ํŽ˜์ด์ง€ ๋งŒ๋“ค๊ธฐ

๋จผ์ €, ํŽ˜์ด์ง€๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ๋Š” polls/urls.py์— ์–ด๋–ค url๋กœ ์ถ”๊ฐ€ํ•  ๊ฒƒ์ธ์ง€ ์ •์˜ํ•œ๋‹ค.

from django.urls import path
from . import views

app_name = 'questions' # app_name์„ ๋งŒ๋“ค์–ด์ฃผ๋ฉด, ๋‹ค๋ฅธ ํ•˜์œ„ url name์ด ๊ฐ™์•„์„œ ํ˜ผ๋™๋˜๋Š” ๊ฑธ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค!
urlpatterns = [
    path('', views.index, name='index'),
    path('some_url', views.some_url),
    path('<int:question_id>/', views.detail, name='detail'), # ์ถ”๊ฐ€ํ•œ ๋ถ€๋ถ„
]

detail ํŽ˜์ด์ง€๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด urls.py์— ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ์‚ฝ์ž…ํ•˜์˜€๋‹ค.

์ด์ œ, < > ์•ˆ์˜ int๋กœ ๋ฐ›์•„์˜ค๋Š” question_id๋ฅผ ๊ฒฝ๋กœ๋กœ ์‚ฌ์šฉํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.

 

๋‹ค์Œ์œผ๋กœ, ์‹ค์ œ polls/views.py์— ๋‹ค์Œ ๋ฌธ๊ตฌ๋ฅผ ์‚ฝ์ž…ํ•˜์—ฌ detail ํŽ˜์ด์ง€๋ฅผ ์ •์˜ํ•œ๋‹ค.

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

์•„๊นŒ context์— dict ํ˜•ํƒœ๋ฅผ ์ •์˜ํ•˜๊ณ  ๋„˜๊ฒจ์ค€ ๊ฒƒ๊ณผ ๋‹ค๋ฅด๊ฒŒ, ์ด๋ฒˆ์—๋Š” renderํ•จ์ˆ˜ ์ธ์ž์— ์ง์ ‘ dict๋ฅผ ๋„ฃ์–ด์คฌ๋‹ค.

render ํ•จ์ˆ˜์—์„œ detail.html์„ ๊ทธ๋ฆฌ๊ธฐ๋กœ ํ–ˆ์œผ๋‹ˆ, detail.html๋„ ํ•„์š”ํ•  ๊ฒƒ์ด๋‹ค.

 

polls/templates ์•ˆ์— detail.html์„ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋งŒ๋“ค์–ด ์ฃผ์—ˆ๋‹ค.

<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

render์—์„œ url์— ์ž…๋ ฅํ•œ question_id์— ํ•ด๋‹นํ•˜๋Š” question์„ ๋ฐ›์•„์™”์œผ๋‹ˆ, ์ด๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ•„์š”ํ•œ ๋ถ€๋ถ„์„ ์ถœ๋ ฅํ•ด๋ณด์•˜๋‹ค.

 

์ €์žฅํ•˜๊ณ  ์‚ฌ์ดํŠธ์—์„œ ํ™•์ธํ•ด๋ณด๋ฉด..

url์„ ์ž˜ ํ™•์ธํ•ด๋ณด์ž. question_id = 1์ธ question๊ณผ ๊ทธ choice๋“ค์ด ์ž˜ ๋‚˜ํƒ€๋‚˜๊ณ  ์žˆ๋‹ค!

 

 

์ƒ์„ธ (detail) ํŽ˜์ด์ง€ ์•ˆ์— ๋งํฌ ์ถ”๊ฐ€ํ•ด๋ณด๊ธฐ

url์— ์ง์ ‘ ์ž…๋ ฅํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์‚ฌ์ดํŠธ ์•ˆ์—์„œ ๋งํฌ๋ฅผ ํƒ€๊ณ  ์ด๋™ํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด์•˜๋‹ค.

 

html์„ ๊ณต๋ถ€ํ•  ๋•Œ ์‚ฌ์šฉํ–ˆ๋˜ ๋งํฌ ํƒœ๊ทธ.. a ํƒœ๊ทธ๋ฅผ ๋˜‘๊ฐ™์ด html์— ๊ตฌํ˜„ํ•˜๋ฉด ๋œ๋‹ค!

index.html โ–ถ detail.html๋กœ ์ด๋™ํ•  ๊ฒƒ์ด๋ฏ€๋กœ index.html์— aํƒœ๊ทธ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

a ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์ด๋™ํ•  url์— ์ž‘์„ฑ์— ์ฃผ์˜ํ•˜์ž.

{% if questions %} <!-- questions์ด ์—†์„ ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ -->
<ul>
    {% for question in questions %}
         <li><a href="{% url 'questions:detail' question.id %}">{{ question.question_text }}</a></li>
    {% endfor %}
<ul>
{% else %}
<p>no questions</p>
{% endif %}

question_text๋ฅผ ๋‚˜ํƒ€๋ƒˆ๋˜ ๋ถ€๋ถ„์— a ํƒœ๊ทธ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ๋‹ค.

์–ด๋–ค url๋กœ ์ด๋™ํ•˜๋Š”์ง€ ๋ณด๋ฉด, ํ˜•ํƒœ๊ฐ€ ์กฐ๊ธˆ ํŠน์ดํ•˜๋‹ค.

 

ํ•œ ๋ถ€๋ถ„์”ฉ ๋‚˜๋ˆ„์–ด ๋ณด๋ฉด..

{% url 'questions:detail' question.id %}

  • url : url ์„ ์‚ฌ์šฉํ•˜๊ฒ ๋‹ค๋Š” ๋ช…์‹œ
  • 'questions:detail' : urls.py์— ๋ช…์‹œ๋œ 'app_name:path_name' ์˜ ํ˜•ํƒœ๋ฅผ ๊ฐ–์ถ˜๋‹ค!
  • question.id : ํ•ด๋‹น path์—์„œ ํ•„์š”ํ–ˆ๋˜ ๋ฐ์ดํ„ฐ, question.id๋ฅผ ๋ณด๋‚ด์•ผํ•˜๋ฏ€๋กœ ๋งˆ์ง€๋ง‰ ์ธ์ž๋กœ ๋„ฃ์–ด์ค€๋‹ค!

 

๋งํฌ ์ฒ˜๋ฆฌ๊ฐ€ ๋œ ๋ชจ์Šต, ๋ˆ„๋ฅด๋ฉด ํ•ด๋‹น question์˜ detail ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•œ๋‹ค.

 

 


 

404 ์—๋Ÿฌ ์ฒ˜๋ฆฌํ•˜๊ธฐ

๋‹ค์Œ์€ url์— ๋“ค์–ด๊ฐ€๋Š” question_id๋ฅผ ์ž˜๋ชป ์ž…๋ ฅํ–ˆ์„ ๋•Œ ๋‚˜ํƒ€๋‚˜๋Š” ์˜ค๋ฅ˜ ํ™”๋ฉด์ด๋‹ค.

๊ฐœ๋ฐœ์ž ๋„๊ตฌ๋กœ ํ™•์ธํ•ด๋ณด๋ฉด, 404๊ฐ€ ์•„๋‹Œ 500์˜ ์˜ค๋ฅ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๊ณ ์žˆ๋‹ค.

์„œ๋ฒ„์˜ ์ž˜๋ชป(500)์ด ์•„๋‹Œ ์š”์ฒญ์˜ ์ž˜๋ชป(404)์ด๋ฏ€๋กœ, 404์—๋Ÿฌ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„๋ณด์ธ๋‹ค!

 

์—ฌ๊ธฐ์„œ ๋ฐ‘์œผ๋กœ ์กฐ๊ธˆ๋งŒ ์Šคํฌ๋กคํ•ด๋ณด๋ฉด, ์–ด๋””์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

detail.py์˜ 16 line์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค

 

์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ตฌ๊ฐ„์—์„œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

from django.http import HttpResponse, Http404
from .models import *
from django.shortcuts import render

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, 'detail.html', {'question' : question})

polls/detail.py ์ฝ”๋“œ์˜ ์ผ๋ถ€์ด๋‹ค.

์ด์ฒ˜๋Ÿผ ๋Š˜ํ•˜๋˜ python์˜ try ~ except ๊ตฌ๋ฌธ์œผ๋กœ ์—๋Ÿฌ์ฒ˜๋ฆฌ๋ฅผ ํ•ด๋„ ์ข‹๋‹ค.

 

ํ•˜์ง€๋งŒ Django์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ๊ฐ€ ๋นˆ๋ฒˆํ•˜๋ฏ€๋กœ ๋”ฐ๋กœ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•œ๋‹ค.

from django.http import HttpResponse
from .models import *
from django.shortcuts import render, get_object_or_404

def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id) # Django์˜ get Error 404์ฒ˜๋ฆฌ
    return render(request, 'detail.html', {'question' : question})

get_object_or_404( getํ•  ๋ชจ๋ธ , ์กฐ๊ฑด )

์ด๋ ‡๊ฒŒ ํ•œ์ค„์ด๋ฉด ์†์‰ฝ๊ฒŒ 404 ์—๋Ÿฌ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค!

 


 

๐ŸŸฆ ํผ(Forms)

์ƒ์„ธ ํŽ˜์ด์ง€ ํ™”๋ฉด์—์„œ ์–ด๋–ค choice๋ฅผ ์„ ํƒํ•˜๋ฉด, ํ•ด๋‹น choice์˜ vote๋ฅผ 1 ์˜ฌ๋ฆฌ๋Š” ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด๋ณด๊ฒ ๋‹ค.

 

html ๊ฐ•์˜์—์„œ ๋ฐฐ์› ๋˜ ๋Œ€๋กœ, form ํƒœ๊ทธ์˜ input์„ ํ™œ์šฉํ•˜์—ฌ ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•œ๋‹ค.

<form action="{% url 'questions:vote' question.id %}" method="post">
    {% csrf_token %} <!-- ๊ฐ„๋‹จํ•œ ํ† ํฐ ์ƒ์„ฑ -->
    <h1>{{question.question_text}}</h1>

    {% for choice in question.choice_set.all %} <!-- Shell๊ณผ ๋‹ค๋ฅด๊ฒŒ all()์˜ ๊ด„ํ˜ธ๋Š” ํ•„์š” ์—†์Œ -->
        <input type="radio" name="choice" id="chocie{{ forloop.counter }}", value="{{choice.id}}"> <!-- forloop๋Š” loop๊ฐ€ ๋Œ๋•Œ๋งˆ๋‹ค ์นด์šดํ„ฐ๊ฐ€ 1์”ฉ ์ฆ๊ฐ€ํ•จ -->
        <label for="chocie{{ forloop.counter }}">
            {{choice.choice_text}}
        </label>
        <br>
    {% endfor %}

<input type="submit", value="Vote">
</form>
  • form ํƒœ๊ทธ๋ฅผ ๋ณด๋ฉด, action์— url์„ ๋„ฃ์—ˆ๋‹ค. ์•„๊นŒ ๋ฐฐ์› ๋˜๋Œ€๋กœ, { app_name : path_name }์˜ ํ˜•ํƒœ์ธ๋ฐ, path_name์ด ์ƒˆ๋กœ์šด vote๋กœ ์ •์˜ํ–ˆ๋‹ค. ์ด vote๋Š” ๋‚˜์ค‘์— urls.py์— ์ถ”๊ฐ€ํ•œ๋‹ค.
  • {% csrf_token %} ์€ ์ž๋™์œผ๋กœ ํ† ํฐ์„ ์ถ”๊ฐ€ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค. ์ด๊ฒŒ ์—†์œผ๋ฉด ํ† ํฐ์ด ์—†๋‹ค๊ณ  ์˜ค๋ฅ˜ ๋ฐœ์ƒ
  • choice๋งˆ๋‹ค radio input์ด ํ•„์š”ํ•˜๋ฏ€๋กœ for๋ฌธ์•ˆ์— ๋„ฃ์–ด์ฃผ์—ˆ๋‹ค.
    • ๋ชจ๋“  radio๊ฐ€ ๋˜‘๊ฐ™์€ "choice" name์„ ๊ฐ€์ง€๋ฏ€๋กœ, ๊ทธ ์ค‘ ํ•˜๋‚˜๋งŒ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋‹ค.
    • id๋Š” forloop์— ์˜ํ•ด ์ž๋™์œผ๋กœ 1์”ฉ ์ฆ๊ฐ€๋œ ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง„๋‹ค.
    • value๋Š” choice.id๋ฅผ ๊ฐ€์ง€๋Š”๋ฐ, ๋‚˜์ค‘์— ์ด value ๊ฐ’์„ ์กฐํšŒํ•˜์—ฌ ํ•ด๋‹น choice์˜ vote๋ฅผ 1 ์˜ฌ๋ ค์ค„ ๊ฒƒ์ด๋‹ค.
  • ๋งˆ์ง€๋ง‰์— Vote๋ผ๋Š” ์ด๋ฆ„์˜ ๋ฒ„ํŠผ์œผ๋กœ ์ œ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์•„๊นŒ ๋งํ–ˆ๋˜ vote๋ฅผ ๋ฐ”๋กœ polls/urls.py์— ์ถ”๊ฐ€ํ•ด๋ณด์ž.

path('<int:question_id>/vote/', views.vote, name='vote'),

detail์ด ๋ฐ›๋˜ ๊ฒƒ์ฒ˜๋Ÿผ question_id๋ฅผ ๋˜‘๊ฐ™์ด ๋ฐ›์•„์˜ค๊ณ , ๊ทธ ๋’ค์— /vote ๊ฒฝ๋กœ๋ฅผ ์ถ”๊ฐ€ํ•œ ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง„๋‹ค.

 

url์˜ path๋กœ ๊ฒฝ๋กœ๋ฅผ ๋งŒ๋“ค์—ˆ์œผ๋‹ˆ ๋ฐ”๋กœ views.py์— ์–ด๋–ป๊ฒŒ ํ•  ๊ฒƒ์ธ์ง€ ์ž‘์„ฑํ•ด์ค€๋‹ค.

from django.http import HttpResponseRedirect # ์‚ฌ์šฉ์ž๋ฅผ ๋‹ค๋ฅธํŽ˜์ด์ง€๋กœ ๋ณด๋‚ด๋Š” ๊ธฐ๋Šฅ
from django.urls import reverse
def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    selected_choice = question.choice_set.get(pk=request.POST['choice'])    
    selected_choice.votes += 1
    selected_choice.save()
    return HttpResponseRedirect(reverse('questions:index'))
  • get_object_or_404๋กœ Question์—์„œ get ๊ธฐ๋Šฅ๊ณผ ํ•จ๊ป˜ ์—๋Ÿฌ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • ๊ฐ€์ ธ์˜จ question ์˜ค๋ธŒ์ ํŠธ์—์„œ requset.POST['choice'] ๋ฅผ ํ†ตํ•ด ์„ ํƒํ–ˆ๋˜ choice๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
    • ์—ฌ๊ธฐ์„œ 'choice'๋Š”, ์•„๊นŒ input radio ํƒ€์ž…์—์„œ name์œผ๋กœ ์ •์˜ํ–ˆ๋˜ 'choice'๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
  • HttpResponseRedirect ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ฉด, ์‚ฌ์šฉ์ž๋ฅผ ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋กœ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ๋งŒ ํ•˜๋ฉด, ์‚ฌ์šฉ์ž๊ฐ€ radio ๋ฒ„ํŠผ์„ ์„ ํƒํ–ˆ์„ ๋•Œ๋Š” ์ •์ƒ์ž‘๋™ํ•˜์ง€๋งŒ ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์ด๊ฒƒ๋„ ๊ฐ™์ด ์ฒ˜๋ฆฌํ•ด์•ผํ•œ๋‹ค.

 

์•„๊นŒ์˜ views.py์˜ vote๋ฅผ try ~ except ๊ตฌ๋ฌธ์œผ๋กœ ์—๋Ÿฌ ์ฒ˜๋ฆฌํ•œ๋‹ค.

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, 'detail.html', {'question':question, 'error_message': '์„ ํƒ์ด ์—†์Šต๋‹ˆ๋‹ค'})
    else:   
        selected_choice.votes += 1
        selected_choice.save()
        return HttpResponseRedirect(reverse('questions:index'))

KeyError : ์•„๋ฌด๊ฒƒ๋„ ์„ ํƒํ•˜์ง€ ์•Š์•˜์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜

Choice.DoesNotExist : get์—์„œ ์—†๋Š” Choice๋ฅผ ์ฐพ์œผ๋ ค๊ณ  ํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜

 

์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด detail.html๋กœ ๋˜‘๊ฐ™์ด ๋ Œ๋”๋ง๋˜์ง€๋งŒ, error_message๋ฅผ ํ•จ๊ป˜ ๊ฐ€์ ธ๊ฐ„๋‹ค.

๊ฐ€์ ธ๊ฐ„ error_message๋ฅผ detail.html์—์„œ ์ฒ˜๋ฆฌํ•˜๋ฉด ๋!

 

detail.html์— ํ•ด๋‹น ๊ตฌ๋ฌธ์„ ์ถ”๊ฐ€ํ•˜์˜€๋‹ค.

    {% if error_message %}
    <p><strong>{{ error_message }}</strong></p>
    {% endif %}

 

์„ ํƒํ•˜์ง€ ์•Š๊ณ  ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €๋”๋‹ˆ, ์—๋Ÿฌ๊ฐ€ ์ž˜ ์ฒ˜๋ฆฌ๋œ ๋ชจ์Šต.

 


 

์—๋Ÿฌ ๋ฐฉ์–ดํ•˜๊ธฐ

ํ•ญ์ƒ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ •์ƒ์ž‘๋™ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š๊ณ , ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๊ฒฝ์šฐ๋ฅผ ๋”ฐ์ ธ ์—๋Ÿฌ๋ฅผ ๋ฐฉ์–ดํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค!

 

  • vote๋ฅผ ํ•˜๋Š” ๋„์ค‘ ํ•ด๋‹น choice๊ฐ€ DB์—์„œ ์‚ฌ๋ผ์ง„ ๊ฒฝ์šฐ โ–ถ Choice.DoesNotExist ์ฒ˜๋ฆฌ ํ•„์š”
  • ์„œ๋กœ ๋‹ค๋ฅธ ์„œ๋ฒ„์—์„œ ๊ฐ™์€ DB๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, ๋™์‹œ์— votes๋ฅผ ์ฆ๊ฐ€์‹œํ‚จ ๊ฒฝ์šฐ โ–ถ ์„œ๋ฒ„๊ฐ€ ์•„๋‹Œ, DB์—์„œ ์ฒ˜๋ฆฌํ•˜๋ฉด ๋จ

DB์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๊ฐ„๋‹จํ•˜๋‹ค. django ๊ธฐ๋Šฅ์ธ F๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

from django.db.models import F
selected_choice.votes = F('votes') + 1 # F๋Š” DB์—์„œ ๋ฐ”๋กœ ๊ฐ’์„ ๋ถˆ๋Ÿฌ์˜ด

F๋ฅผ importํ•ด์ฃผ๊ณ , votes์˜ ์—ฐ์‚ฐ์„ ์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ ๋ฐ”๊ฟ”์ค€๋‹ค.

F๋Š” 'votes'๋ฅผ DB์—์„œ ๋ฐ”๋กœ ์ฐธ์กฐํ•˜์—ฌ ๊ฐ€์ ธ์˜ค๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ ์„œ๋ฒ„์—์„œ ์—ฐ์‚ฐํ•˜์—ฌ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๋Š” ์ƒํ™ฉ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 


 

๊ฒฐ๊ณผ(result) ์กฐํšŒ ํŽ˜์ด์ง€ ๋งŒ๋“ค๊ธฐ

์ƒ์„ธ ํŽ˜์ด์ง€ ๋งŒ๋“ค๊ธฐ์™€ ์œ ์‚ฌํ•˜๋ฏ€๋กœ ๋น„์Šทํ•œ ๊ณผ์ •์€ ํŒจ์Šคํ–ˆ๋‹ค.

๋”๋ณด๊ธฐ

๊ฐ ์ถ”๊ฐ€ํ•œ ๋‚ด์šฉ


polls/views.py

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

 

polls/templates/polls/result.html

<h1>{{ question.question_text }}</h1><br>
{% for choice in question.choice_set.all %}

    <label>
        {{ choice.choice_text }} -- {{ choice.votes }}
    </label>
    <br>
{% endfor %}

 

polls/urls.py

from django.urls import path
from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
    path('<int:question_id>/result/', views.result, name='result'),
]

 

ํˆฌํ‘œ ์ดํ›„ result ํŽ˜์ด์ง€๋กœ ์ด๋™์‹œํ‚ค๊ธฐ ์œ„ํ•ด polls/views.py์—์„œ vote์˜ return์„ ์ˆ˜์ •ํ–ˆ๋‹ค.

return HttpResponseRedirect(reverse('questions:result', args= (question_id,)))

questions:result๋ฅผ ํ†ตํ•ด resultํ™”๋ฉด์œผ๋กœ ๋„˜์–ด๊ฐ”์œผ๋ฉฐ, args๋กœ ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

๊ผญ ํ•„์š”ํ•œ ์ธ์ž question_id๋ฅผ ๋„ฃ์–ด๋‘”๋‹ค.

 


 

 

๐Ÿค” ๊ณต๋ถ€ํ•˜๋ฉด์„œ ์–ด๋ ค์› ๋˜ ๋‚ด์šฉ

์›น ์‚ฌ์ดํŠธ๋ฅผ ๋‹ค๋ฃจ๋ฉด์„œ ๊ฒฝ๋กœ๋ฅผ ์ด๋ฆฌ์ €๋ฆฌ ๋งž์ถฐ ์„ค์ •ํ•ด์ฃผ๋Š” ์ ์ด ์กฐ๊ธˆ ์–ด๋ ค์› ๋‹ค.

์•„๋ฌด๋ž˜๋„ ์ด๋Ÿฌํ•œ ๋ถ€๋ถ„์— ํ™•์‹คํ•œ ์ดํ•ด๊ฐ€ ํ•„์š”ํ•  ๊ฒƒ ๊ฐ™๋‹ค.. ๋‹ค์Œ์— ๊ผญ ๋ณต์Šตํ•ด๋ด์•ผ์ง€..

Django์˜ ์ƒˆ๋กœ ๋ฐฐ์šด ๊ธฐ๋Šฅ๋„ ์—ฌ๋Ÿฌ ๊ฐ€์ง€์žˆ์—ˆ๊ณ , ํŒŒ์ด์ฌ๋งŒ ํ•ด๋„ *args, **kwargs๋Š” ์ฒ˜์Œ ์จ๋ณด๋Š” ๊ธฐ๋Šฅ์ด์—ˆ๋‹ค.

์—ฌ๋Ÿฌ๋ฒˆ ๋‹ค์‹œํ•ด๋ณด์ง€์•Š์œผ๋ฉด ๊นŒ๋จน์„ ๊ฒƒ ๊ฐ™์œผ๋‹ˆ.. ๋”๋ฏธ ํ”„๋กœ์ ํŠธ๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด๋ด์•ผ๊ฒ ๋‹ค.

'TIL' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[TIL]KDT_20230427  (0) 2023.04.27
[TIL]KDT_20230426  (0) 2023.04.26
[TIL]KDT_20230424  (0) 2023.04.24
[TIL]KDT_20230421  (0) 2023.04.21
[TIL]KDT_20230420  (0) 2023.04.20