에러 처리하기
404에러 처리하기
polls/views.py에서
from models.py import *
from django.http import HttpResponse
from django.http import Http404
from django.shortcuts import render , get_object_or_404 #장고에서 기본 제공되는 에러 처리 툴
...
def detail(request, question_id):
"""
try:
question = Question.objects.get(pk=question_id)
except Question.DoesNotExist:
raise Http404("Question does not exist")
"""
#위의 4줄이 다음 코드 한줄로 대체 가능하다.
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})
투표 받기 기능 에러 처리하기
polls/templates/polls/detail.html에서
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %} #Vote버튼을 누르면 그 값을 받을 토큰 생성하기
<h1>{{ question.question_text }}</h1>
{% 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 }}">#input의 이름이 choice임.
<label for="choice{{ forloop.counter }}">
{{ choice.choice_text }}
</label>
<br>
{% endfor %}
<input type="submit" value="Vote">
</form>
polls/views.py에서
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']) #input이름이 choice였으므로
except (KeyError, Choice.DoesNotExist): # 선택 안하고 vote만 눌러버린 경우 에러가 발생하므로 예외처리를 해준다.
return render(request, 'polls/detail.html', {'question': question, 'error_message': '선택이 없습니다.'})
else:
selected_choice.votes += 1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:index'))
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'),
]
에러 미리 방어하기
만일 여러 접속자가 있을 때 vote를 동시에 누르게 된다면 카운트가 안될 수도 있다.
이를 예방하기 위해 F라는 모듈을 이용한다.
polls/views.py에서
from django.urls import reverse
from django.db.models import F
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': f"선택이 없습니다. id={request.POST['choice']}"})
else:
# A서버에서도 Votes = 1
# B서버에서도 Votes = 1
selected_choice.votes = F('votes') + 1 #F 이용
selected_choice.save()
return HttpResponseRedirect(reverse('polls:index'))
커스터마이징
결과 조회 페이지 만들기
polls/views.py에서
from django.shortcuts import get_object_or_404, render
...
def vote(request, question_id):
...# 위의 코드에서 이 부분부터 수정
else:
selected_choice.votes = F('votes') + 1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:result', args=(question.id,))) # 주의) question.id,에서 ,가 없으면 에러남
def result(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/result.html', {'question': question})
결과를 알려줄 새로운 html 페이지 만들기
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'),
]
admin의 편집 페이지 커스터마이징하기
polls/admin.py에서
from django.contrib import admin
from .models import Choice, Question
admin.site.register(Choice)
class ChoiceInline(admin.TabularInline): # 선택지와 투표횟수가 한 줄에 출력됨
model = Choice
extra = 3 # 추가 선택지 3개로 설정
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
('질문 섹션', {'fields': ['question_text']}),
('생성일', {'fields': ['pub_date'], 'classes': ['collapse']}), # 'classes': ['collapse'] ->숨기기 기능 추가
]
readonly_fields = ['pub_date']
inlines = [ChoiceInline]
admin.site.register(Question, QuestionAdmin)
admin의 목록 페이지 커스터마이징하기
polls/models.py에서
import datetime
from django.db import models
from django.utils import timezone
from django.contrib import admin
class Question(models.Model):
question_text = models.CharField(max_length=200, verbose='질문')
pub_date = models.DateTimeField(auto_now_add=True, verbose='생성일')
#boolean=True를 하면 체크박스로 보여줌
@admin.display(boolean=True, description='최근생성(하루기준)')
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
def __str__(self):
return f'제목: {self.question_text}, 날짜: {self.pub_date}
polls/admin.py에서
from django.contrib import admin
from .models import Choice, Question
admin.site.register(Choice)
class ChoiceInline(admin.TabularInline):
model = Choice
extra = 3
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
('질문 섹션', {'fields': ['question_text']}),
('생성일', {'fields': ['pub_date'], 'classes': ['collapse']}),
]
readonly_fields = ['pub_date']
inlines = [ChoiceInline]
list_filter = ['pub_date'] #생성일 필터가 오른쪽에 생김
search_fields = ['question_text', 'choice__choice_text'] #검색 상자 만들기 질문과 선택지 기준 검색
admin.site.register(Question, QuestionAdmin)
'AI > 데이터 엔지니어링 데브코스' 카테고리의 다른 글
[3주차-3] 장고를 활용한 API서버 만들기 - HTTP Methods 기반의 views (0) | 2023.04.29 |
---|---|
[3주차-3] 장고를 활용한 API서버 만들기 - Serialize (0) | 2023.04.29 |
[3주차-2] 장고를 활용한 API서버 만들기 - view 다루기 (0) | 2023.04.29 |
[3주차-1] 장고를 활용한 API서버 만들기 - 장고 admin, 모델 필터링 (0) | 2023.04.29 |
[3주차-1] 장고를 활용한 API서버 만들기 - Django 시작하기 (0) | 2023.04.25 |