티스토리 뷰

※본 자료는 김석훈, 『파이썬 웹 프로그래밍(개정판)』, 한빛미디어, pp151-218. 를 참고하여 만들었습니다.

4. 폼처리하기

(1) HTML에서의 폼

 

 우리는 웹사이트를 개발할 때 사용자로부터 입력을 받기 위해서 폼을 사용합니다. HTML로 표현하면 폼은

<form> ... </form> 사이에 있는 엘리먼트들의 집합입니다. 폼에 입력된 데이터는 서버로 보내집니다. 텍스트 입력이나 체크 박스 등과 같은 간단한 폼의 엘리먼트들은 기본 위젯을 사용하지만, 달력 위젯, 슬라이드 바 등의 복잡한 엘리먼트들은 자바스크립트나 CSS를 사용하기도 합니다.

 폼은 <input> 엘리먼트 외에도 폼 데이터를 어디로 보낼지 지정해주는 action 속성과 어떤 HTTP 메소드로 보낼지 지정해주는 method 속성을 설정해주어야 합니다.

 HTTP 프로토콜 중 폼에서 사용할 수 있는 HTTP 메소드는 GET과 POST뿐입니다. 장고에서는 이 중에서 폼의 데이터를 전송할 때는 POST 방식만을 사용하고 있습니다.

 

 

(2) 장고의 폼 기능

 

 웹 서버에서의 폼 처리는 복잡한 과정이지만 공통적인 절차를 갖고 있습니다. 여러 가지 타입의 많은 위젯이 폼 화면 출력용으로 준비되어야 하고, HTML 렌더링되며, 적절한 인터페이스를 사용하여 입력 및 수정되고, 서버로 보내져서 데이터가 유효한지 검증을 거친 후에 적절한 처리를 위해 저장되거나 전달됩니다.

 장고에서는 이러한 폼 처리를 위하여 다음의 3가지 기능을 제공합니다.

  1. 폼 생성에 필요한 데이터를 폼 클래스로 구조화하기
  2. 폼 클래스의 데이터를 렌더링하여 HTML 폼 만들기
  3. 사용자로부터 제출된 폼과 데이터를 수신하고 처리하기

 웹 개발에 있어서 폼이라는 용어는 1. HTML의 <form>을 지칭할 수도 있고, 2. <form>을 만들어내는 장고의 Form 클래스일 수도 있고, 3. 서버로 제출된 구조화된 데이터일 수도 있습니다. 또한 이 모든 것을 통칭해서 폼이라고 합니다. 이 중에서 가장 핵심적인 컴포넌트는 장고의 폼 클래스입니다. 폼 클래스는 폼을 기술하고 폼이 어떻게 작동하고 어떻게 보이는지를 결정합니다.

 폼 클래스의 필드는 HTML 폼의 <input> 엘리먼트에 매핑됩니다. 폼 클래스도 역시 클래스임으로, 필드는 저장하는 데이터의 종류에 따라 자신의 타입을 가지고 그에 따라 자신의 데이터에 대한 유효성 검사를 실시힙나디. 또한, 폼의 필드는 브라우저에서 HTML위젯으로 표현되고, 필드 타입마다 디폴트 위젯 클래스를 가지고 있으며 필요 시 오버라이딩될 수 있습니다.

 폼도 결국 템플릿의 일부이므로 템플릿 코드에 포함되어서 렌더링 절차를 거칩니다. 장고의 렌더링 절차는 다음의 3단계 과정을 거칩니다. 

 

  1. 랜더링할 객체를 뷰로 가져오기 (예를 들어, 데이터베이스로부터 객체를 추출하기)
  2. 그 객체를 템플릿 시스템으로 넘겨주기
  3. 템플릿 문법을 처리해서 HTML 마크업 언어로 변환하기

 폼도 객체이기 때문에 템플릿에서 폼을 렌더링하는 작업은 위와 같은 객체를 렌더링하는 것과 거의 동일한 작업이지만, 폼 객체에는 데이터가 없을 수도 있다는 점을 주의해야 한다. 폼 객체는 렌더링 이후에 사용자가 데이터를 채우는 것이 보통이므로, 빈 객체를 렌더링 하는 일이 자주 발생하게 됩니다 따라서 뷰 함수에서 폼 객체를 생성할 때는 데이터없이 만들 것인지, 아니면 데이터를 채워서 만들 것인지 적절히 구분해서 코딩해야 합니다. 데이터를 채울 때는 저장된 모델 객체로부터 채울 수도 있고, 또는 직전에 제출된 HTML 폼으로부터 채울 수도 있습니다. 직전에 제출된 HTML 폼으로부터 채우는 경우는 폼 필드가 여러 개 일 때, 하나의 필드에서 에러가 발생하여 다시 폼 데이터를 입력할 때 에러가 없는 다른 필드들은 직전에 제출된 폼으로부터 데이터를 채우고 사용자에게 보요주는 경우 활용 될 수 있습니다. 데이터가 없는 폼을 언바운드 폼이라고 하며, 사용자가 입력하여 데이터가 입력되어 있는 폼을 바운드 폼이라고 합니다. 바운드 폼을 이용하여 장고는 데이터 유효성 검사를 합니다.

 

(3) 폼 클래스로 폼 생성

장고에서는 폼도 클래스로 정의해서 간편하게 만들 수 있습니다. 다음과 같은 템플릿 코드를 form을 장고의 폼 클래스를 이용해서 만들어 봅시다.

<form action="/your-name/" method="post">
    <label for="your_name">Your name:<label>
    <input id="your_name" type="text" name="your_name" value="{{current_name}}">
    <input type="submit" value="OK">
</form>

브라우저에 출력되는 form

 위 예제는 POST 방식을 이용해서 브라우저에게 폼 데티어를 URL /your-name/으로 보내달라고 요청하고 있습니다.

{{ current_name }} 템플릿 변수는 템플릿 렌더링요청하는 뷰에서 그 변수값을 지정해줄 것입니다. 폼이 제출되면 POST 요청에 폼 데이터가 담겨서 서버로 보내집니다. 그리고 URL /your-name/에 해당하는 뷰가 있어서, 요청 데이터에서 이름/값 쌍을 찾아서 뷰의 로직에 따라 적절한 처리를 할 것입니다.

 

 장고는 이와 같은 <form> 엘리먼트의 기능을 제공하기 위하여 다음과 같은 폼 클래스를 정의합니다.

(모든 폼 클래스는 django.forms.Form 의 자식 클래스로 생성됩니다.)

 

from django import forms

class NameForm(forms.Form):
	your_name = forms.CharFeild(label='Your name', max_length=100)

 각각의 폼 필드는 위젯 클래스를 갖고 있고, 이 위젯 클래스는 HTML 폼 위젯으로 대응됩니다. CharField필드 타입은 TextInput 위젯이 디폴트 위젯이며 HTML <input type="text">로 변환됩니다. 만일 디폴트 위젯으 <textarea>로 변경하려면 다음과 같이 폼 필드를 정의할 때 명시적으로 저징하면 됩니다.

from django import forms

class NameForm(forms.Form):
	your_name = forms.CharFeild(label='Your name', max_length=100 widget=forms.Textarea)

 장고의 폼 클래스는 모든 필드에 대해 유효성 검사 루틴을 실행시키는 is_valid() 메소드를 갖고 있습니다. 이 메소드가 호출되어 유효성 검사를 하고, 그 결과 만일 모든 필드가 유효하다면 is_valid()메소드는 True를 반환하고, 폼 데이터를 cledned_data 속성에 넣습니다.

 

 위 폼 클래스 코드를 렌더링하면 다음과 같인 HTML 코드가 생성됩니다.

<label for="your_name">Your name:</label>
<input id = "your_name" type="text" name="your_name" maxlength="100">

 렌더링 결과에 <form> 태그나 submit 버튼은 없습니다. 이들은 개발자가 직접 템플릿에 넣어줘야 됩니다. 그래서 템플릿 코드에는 다음과 같이 코딩하면 됩니다.

 

<form action="/your-name/" method="post">
    {% csrf_token %}
    {{ form }}
    <input type="submit" value="Submit" />
 </form>

폼 클래스는 {{ form }} 변수로 사용하였습니다. {{ form }} 변수는 뷰에서 컨텍스트 변수에 포함하여 템플릿 시스템으로 넘겨주게 됩니다.

 

(4) 뷰에서 폼 클래스 처리

 폼을 처리하는 뷰는 2개가 필요합니다. 하나는 폼을 보여주는 뷰이고, 다른 하나는 제출된 폼을 처리하는 뷰 입니다. 장고에서는 이 두 기능을 하나의 뷰로 통합하여 폼을 처리하는 것을 권장하고 있습니다. HTTP 메소드로 이를 구분 가능한데, 뷰가 GET 방식으로 요청을 받은 경우세는 사용자에게 처음으로 폼을 보여주도록 처리하고, 뷰가 POST 방식으로 요청을 받은 경우에는 데이터가 담긴 제출된 폼으로 간주하여 처라하게 됩니다.

from django.shortcuts import render
from django.http import HttpResponseRedirect
from  django import forms

class NameForm(forms.Form):
    your_name = forms.CharField(label="Your name",max_length=100)

def get_name(request):
    # POST 방식이면, 데이터가 담긴 제출된 폼으로 간주합니다.
    if request.method == 'POST':
        #request에 담긴 데이터로, 클래스 폼을 생성합니다.
        form = NameForm(request.POST)
        
        #폼에 담긴 데이터가 유효한지 체크합니다.
        if forms.is_valid():
            #폼 데이터가 유효하면, 데이터는 cleaned_data로 복사됩니다.
            new_name = form.cleaned_data['name']
            #로직에 따라 추가적인 처리를 합니다.
            
            #새로운 URL로 리다이렉션 시킵니다.
            return HttpResponseRedirect('/thanks/')
        
   #POST 방식이 아니면 ( GET 요청인 경우 )
   #빈 폼을 사용자에게 보여줍니다.
    else:
        form = NameForm()
        
    return render(request,'name.html',{'form':form})

 

 

(5) 폼 클래스를 템플릿으로 변환

 

{{ form }}  구문은 HTML의 <label>과 <input> 엘리먼트 쌍으로 렌더링 되는데, 이 때 3가지 옵션이 더 있습니다.

  • {{ form.as_table }} : <tr> 태그로 감싸서 테이블 셀로 렌더링 됩니다. {{ form }} 과 동일
  • {{ form.as_p }} : <p> 태그로 감싸도록 렌더링 됩니다.
  • {{ form.as_ul }} : <li> 태그로 감싸도록 렌더링 됩니다.

여기서도 <label>/<input> 태그 쌍을 감싸는 <table> 혹은 <ul> 태그는 개발자가 직접 추가해야합니다. 물론 <form> 태그와 submit 컨트롤도 자동으로 추가되지 않으므로 개발자가 직접 작성해야합니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함