[Django] 폼(Forms)

2024. 10. 8. 16:53·Minding's Programming/Django
728x90
반응형

폼(Forms)

폼은 사용자로부터 데이터를 받을 수 있는 형식을 말한다. 지난 시간([Django] 뷰(views)와 템플릿(templates))에서 다룬 상세 페이지에서 선택지가 단순히 노출되는 것이 아닌 사용자로부터 선택할 수 있게 만들어 보려고 한다.

 

detail.html 수정

<form action="{% url 'polls:vote' question.id %}" method="post">
    {% csrf_token %}
    <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 }}">
        <label for="choice{{ forloop.counter }}">
            {{ choice.choice_text }}
        </label>
        <br>
    {% endfor %}

<input type="submit" value="Vote">
</form>

form의 태그는 데이터를 제출할 용도이기 때문에 post로 지정해준다. input type을 radio로 하는 투표 형태의 input 태그를 설정해준다. 만약 선택하지 않고 submit을 했을 경우 error message가 노출된다. 실제로 form이 액션을 취하는 링크는 polls의 vote라는 path를 따른다고 한다.

 

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'), 
]

위 html파일에서 vote라는 path를 만들어주기 위해 urls.py도 수정해준다. detail과 같이 question_id라는 이름으로 정수를 전달한다. 해당 링크는 views.py의 vote 함수를 작동시켜 사용자에게 전달한다.

 

views.py 수정

from django.shortcuts import render
from django.http import HttpResponse
from .models import Question
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect
from django.urls import reverse
from .models import 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'])
    # Choice.DoesNotExist 사용한 이유: 오류 또는 삭제로 없는 값이 제출되는 것 방어
    except (KeyError, Choice.DoesNotExist):
        return render(request, 'polls/detail.html', {'question': question, 'error_message': '선택이 없습니다.'})
    else:
        selected_choice.votes += 1
        selected_choice.save()
        return HttpResponseRedirect(reverse('polls:index'))

vote라는 함수를 작성했다. 질문을 우선 노출시킨 뒤, 선택된 항목이 있으면 해당 항목(레코드)의 votes를 1 더하고 저장한다. 만약 선택되지 않은 상태라면 에러메시지를 전달해 노출시킨다. detail.html의 상단에 보면 {%if error_message %} 부분이 있는데, 이 메시지가 전달될 때에만 노출된다는 뜻이다.

 

구현된 페이지는 위와 같다. 만약 선택하지 않은채로 Vote 버튼을 누른다면,

'선택이 없습니다.'라는 메시지가 노출되게 된다.

 

다른 서버에서 동시에 같은 폼을 제출했을 때

만약 A서버와 B서버 모두에서 동시에 같은 답변을 제출했다고 생각해보자.

    else:
        selected_choice.votes += 1
        selected_choice.save()

위 코드에서 selected_choice의 값는 A서버와 B서버 모두 같기 때문에 두 서버의 답변 카운트가 정상적으로 반영되지 않을 가능성이 있다. 이를 방지하기 위해서는 아래와 같은 방법을 사용한다.

 

F 메소드 사용

from django.db.models import F

...

    else:
        selected_choice.votes = F('votes') + 1
        selected_choice.save()
        # POST 데이터를 정상적으로 처리했으면, 다른 페이지로 리다이렉트
        return HttpResponseRedirect(reverse('polls:index'))

F()는 해당 코드가 실행될 때 해당 값을 DB에서 불러와 처리한다는 것을 의미한다. 메모리에 저장된 값이 아닌 DB에서 바로 불러오기 때문에, 두 서버에서 동시에 폼을 제출해도 문제 없이 처리할 수 있다.

728x90

'Minding's Programming > Django' 카테고리의 다른 글

[Django] Serilaizer  (4) 2024.10.10
[Django] Admin 페이지 편집  (0) 2024.10.10
[Django] 뷰(views)와 템플릿(templates)  (0) 2024.10.08
[Django] 모델 메소드(Model Method)  (1) 2024.10.08
[Django] 모델 필터링(Model Filtering)  (2) 2024.10.07
'Minding's Programming/Django' 카테고리의 다른 글
  • [Django] Serilaizer
  • [Django] Admin 페이지 편집
  • [Django] 뷰(views)와 템플릿(templates)
  • [Django] 모델 메소드(Model Method)
Minding
Minding
  • Minding
    Today's Minding
    Minding
  • 전체
    오늘
    어제
    • 울고넘는 딥러닝 (278)
      • Minding's Baseball (57)
        • MLB Statcast (29)
        • 머신러닝으로 홈런왕 예측하기 (3)
        • 야구칼럼 (12)
        • 야구 규칙, 용어 (1)
        • 2022-23 질롱 코리아 (8)
        • 류현진 등판경기 (4)
      • Minding's Programming (185)
        • 프로그래머스 코딩테스트 (21)
        • Knowledge (44)
        • Numpy & Pandas (6)
        • Excel (3)
        • Git (1)
        • Pygame (11)
        • CV (3)
        • Tensorflow tutorial (4)
        • Kaggle and Dacon (4)
        • 에러 코드 (8)
        • FastAPI (8)
        • Airflow (29)
        • Crawling (6)
        • Django (14)
        • AWS (18)
        • Spark (5)
      • Minding's Reading (30)
        • 머신러닝 딥러닝에 필요한 기초 수학 with 파이.. (2)
        • 칼만필터는 어렵지 않아 (11)
        • 밑바닥부터 시작하는 딥러닝 (6)
        • 메이저리그 야구 통계학 2e (8)
        • 논문읽기 (2)
        • 빅데이터를 지탱하는 기술 (1)
      • Minding's Life (5)
        • 주식 (4)
        • 각종 소식 (1)
  • 블로그 메뉴

    • 홈
    • Baseball
    • Programming
    • Reading
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    질롱코리아
    django
    머신러닝
    파이썬게임개발
    칼만필터는어렵지않아파이썬
    딥러닝
    KBO
    데이터 엔지니어
    메이저리그
    KalmanFilter
    프로그래머스
    칼만필터
    pygame
    django python
    칼만필터는어렵지않아python
    Python
    코딩테스트
    넘파이
    mlb stats api
    파이게임
    게임개발
    칼만필터는어렵지않아
    데이터분석
    에어플로우
    Airflow
    야구
    FastAPI
    파이썬
    AWS
    MLB
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Minding
[Django] 폼(Forms)
상단으로

티스토리툴바