알쓸전컴(알아두면 쓸모있는 전자 컴퓨터)

django 간단한 폼 만들기 본문

Web /Django

django 간단한 폼 만들기

백곳 2017. 8. 12. 16:22

django 간단한 폼 만들기


일단 예제 코드를 본다음 1개씩 분석을 해보도록 한다.


예제에 앞서 polls/views.py 을 보겠다 

polls/views.py

from django.shortcuts import get_object_or_404, render
# Create your views here.
from django.http import HttpResponse
from .models import Question
def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}   
    return render(request, 'polls/index.html', context)

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

def results(request,question_id):
    return HttpResponse(response % question_id)

def vote(request,question_id):
    return HttpResponse("You're voting on question %s." % question_id)


detail 함수에서 {'question': question} 에서 템플릿에 딕셔너리(사전) 형태로 넘겨 줍니다. 


polls/templates/polls/detail.html

<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>


<h1>{{ question.question_text }}</h1> 제목으로는 question_text 을 가지고 옵니다. 


{% csrf_token %}은 보안의 기법입니다. post로 해서 데이터를 보낼때 패킷이 외부에 유출이 될때 해킹을 못하게 막는 기술중 하나로 


자세한것은 google 웹서치로 찾아보면 좋은 자료가 많습니다. 


그래서 {% csrf_token %} 을 적어줘서 post 메시지를 보내는데에 해킹의 위험에서 안전할수 있습니다.


form태그의 action에는 저번 포스트에서 설명한 url태그가 들어가있고, CSRF(Cross-site Request Forgery) 를 방지하기 위한 태그가 들어가


있다. 이 태그는 위조 방지 토큰을 가지는 Input태그를 생성하여 취약점을 보완해준다


{% for choice in question.choice_set.all %} 


question.choice_set.all은 해당 Question모델을 foreign key로 참조하는 모든 Choice 모델을 가져온다. 

{{ forloop.counter }}

현재 루프 카운터 


{{ choice.id }} and {{ choice.choice_text }}  

DB 안에 있는 값을 알려준다. 


기타로 값을 전달하는 http 방식에 대해서는 http의 전송방식 post get form 을 공부 하셔야 됩니다. 

여기서는 post로 전달 했을때 name은 choice 에 value 값을 넣어 줍니다. 


그리고 여기서 

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

polls/urls.py

url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),

에서 등록한 vote app 으로 값을 전송합니다. 




데이터 추적 


polls/urls.py

url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),

에서 웹접속을 

http://10.23.10.232:8888/polls/1/ 이렇게 하면 

question_id 에 1을 넘겨 주고 

그값이 

polls/views.py

def detail(request,question_id):

    question = get_object_or_404(Question, pk=question_id)

    return render(request, 'polls/detail.html', {'question': question})

detail 함수에 question_id 에  1을 넘겨 주고 


render(request, 'polls/detail.html', {'question': question}) 

에서 polls/detail.html 탬플릿을 가져와서 pk=1 인 DB의 객체를 가져옵니다. 

이렇게 넘겨 줍으로써 템플릿에서 DB에 접근 해서 


위와 같은 화면이 보여지게 되는 것입니다. 



POST 데이터 전송


전송된 데이터를 받아 웹에 어떤 액션을 취하겠습니다. 


위에서 from을 눌러 vote app에 전송이 이루어지도록 코딩을 했습니다.


polls/views.py

from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
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.
        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 HttpResponse("You're voting on question %s." % question_id)
  • request.POST 는 키로 전송된 자료에 접근할 수 있도록 해주는 사전과 같은 객체입니다. 이 경우, request.POST['choice'] 는 선택된 설문의 ID를 문자열로 반환합니다. request.POST 의 값은 항상 문자열들입니다.

    Django는 같은 방법으로 GET 자료에 접근하기 위해 request.GET 를 제공합니다 – 그러나 POST 요청을 통해서만 자료가 수정되게하기 위해서, 명시적으로 코드에 request.POST 를 사용하고 있습니다.

  • 만약 POST 자료에 choice 가 없으면, request.POST['choice'] 는 KeyError 가 일어납니다. 위의 코드는 KeyError 를 체크하고, choice가 주어지지 않은 경우에는 에러 메시지와 함께 설문조사 폼을 다시보여줍니다.

  • 설문지의 수가 증가한 이후에, 코드는 일반 HttpResponse 가 아닌 HttpResponseRedirect 를 반환하고, HttpResponseRedirect 는 하나의 인수를 받습니다: 그 인수는 사용자가 재전송될 URL 입니다. (이 경우에 우리가 URL을 어떻게 구성하는지 다음 항목을 보세요).

    위의 파이썬 주석이 지적했듯이, POST 데이터를 성공적으로 처리 한 후에는 항상 HttpResponseRedirect 를 반환해야합니다. 이 팁은 Django에만 국한되는것이 아닌 웹개발의 권장사항입니다.

일단 여기서는 데이터가 전송 되었을때 

        selected_choice.votes += 1

        selected_choice.save()

votes 을 1을 증가 시켜 세이브 하도록 하는게 목적입니다. 



sudo service apache2 restart


사이트는 위와 같이 뜨고

DB를 보겠습니다. 



votes을 보면 1이 증가함을 알수 있습니다. 


request.POST['choice'] 로 test1을 받아서 voutes을 +1을 해준것이죠. 


'Web > Django' 카테고리의 다른 글

제너릭 뷰 사용하기  (0) 2017.08.14
django HttpResponseRedirect 하기  (0) 2017.08.14
dajngo Template 에서 하드코딩된 URL 을 제거  (0) 2017.08.12
Template 시스템 사용하기  (0) 2017.08.12
django 404 에러 일으키기  (0) 2017.08.12
Comments