Django Form

Django Form 기초

Django는 사이트 방문자로부터 입력을 받아 Form을 작성한 다음 입력을 처리하고 응답하는데 도움이 되는 다양한 도구와 라이브러리를 제공함.

폼 관리는 복잡하다. 그래서 Django 관리자를 사용하면, 다양한 유형의 여러 데이터 항목을 Form으로 표시하고 HTML로 렌더링 하며 편리한 인터페이스를 사용하여 편집하고 서버로 반환하여 유효성을 검사하고 정리 한 다음 저장하거나 나머지 처리를 전달 할 수 있다.

FormDjangoModel과 아주 밀접하게 동작을 하게 할 수 있다. 그래서 상당부분을 단순화하고 자동화를 할 수 있으며, 대부분의 프로그래머들이 작성한 코드보다 더 안전하다.

폼으로 받은 데이터가 실제 모델이 원하는 데이터와 다를 수 있다. 예를 들어 비밀번호 문자수 제한 이라던지, 그런것을 Django Form에서 알아서 해줄 수 있다.

폼은 3가지 파트가 있다

  • 데이터를 렌더링할 준비
  • HTML Form 을 만들고
  • 클라이언트로 부터 제출 된 데이터를 수신하여 처리

모델이 어떤 하나의 논리적 개체를 나타내는 것처럼 폼도 비슷하다. 폼 자체에 대해서 표현방식을 결정한다. 모델 클래스의 필드가 데이터 베이스 필드에 매칭 되는 것과 비슷한 방식으로 폼 클래스의 필드는 HTML 폼 요소에 매핑 된다.

폼의 필드는 그것 자체가 클래스다. 우리가 데이터베이스 컬럼을 만들때도 필드 안에 클래스 인스턴스를 썼는데 폼도 동일하다.

장고에서 Form을 렌더링 할꺼면 viewForm을 가지고 있어야 한다. 폼 클래스로 만든 인스턴스를 컨텍스트로 전달한 다음에 그 컨텐스트로 전달된 값을 HTML markup으로 렌더링 하면 된다.

폼 클래스를 만들어 보자.

from django import forms

class NameForm(forms.Form):
    username = forms.CharField(label='Your name', max_length=100, label_suffix='')

your_nanme 이라는 필드가 있는 폼 클래스를 정의 했다. 사람이 알아 보기 쉽게 적용 했다. label 같은 경우 렌더링이 될 때 <label>로 나타 낸다. 그리고 필드의 max_lengthHTML form에 지정된다. html5에서는 기본적으로 max_length가 제약사항에 걸리기 때문에 이것을 지키지 않은 경우 제출 자체가 안된다. 정확히는 input 자체에 걸리기 때문에 입력 자체가 안된다. 만약 버전이 낮은 브라우저로 해당 max_length를 넘겨서 제출 하게 되면 폼 자체에서 유효성 검사 오류가 자동으로 일어난다.

그리고 Form클래스는 is_valid가 존재 하는데, 모든 필드에 대한 유효성 검사 루틴을 실행한다. 모든 필드에 유효한 데이터가 들어 있으면 True가 리턴되고 해당 폼에 cleaned_data라는 속성이 추가 되고 폼에 들어있는 데이터가 cleaned_data로 이돟한다. 만약 모두 유효하지 못한 데이터가 있을 경우 False가 리턴되고 그 중 유효한 데이터만이 cleaned_data로 이동한다.

뷰에서 일반적으로 사용 하는 방법.

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

from .forms import NameForm

def get_name(request):
    if request.method == 'POST':
    # request.POST를 Form클래스에 전달하면
    # request.POST에 있는 데이터를 Form객체에 채운다
    # 유효성 검증을 할 수 있는 상태로 만들어줌
    # 그래서 이것을 바운딩 된 폼 binded_form 이라고 부른다.
    form = NameForm(request.POST)
    if form.is_valid():
    	thanks = form.cleanded_data['thanks']
    	if thanks:
            return HttpResponseRedirect(thanks)
        else:
            form.add_error('<input name>', '<message>')
    else:
        form = NameForm()
    
    return render(request, 'name.html', {'form':form})
<form action="" method="POST">
	{% csrf_token %}
        {% for field in form %}
        <div>
            {{ field.label_tag }}
            {{ field }}
            {% for error in field.errors %}
            <p>{{ error }}</p>
            {% endfor %}
        </div>
        {% endfor %}
	<div>
	    <button type="submit"></button>
	</div>
</form>

이 뷰에 GET요청이 오면 빈 폼 인스턴스를 만들어 렌더링 할 템플릿 컨텍스르에 넘겨준다. 이것은 해당 페이지를 처음 들어 왔을때 아무 것도 없는 빈 폼이 만들어 져야 하기 때문이다. 그런데 POST요청이 올 경우 폼에 데이터를 바인딩 하여 다시 만든다. 그리고 is_valid()를 호출하여 유효성 검사 통과 여부에 따라 어떤 폼이 들어 갈지 판단 하여 컨텍스트에 전달하여 템플릿으로 렌더링 한다. 그리고 유효성 검사를 통과 한 데이터는 form.cleaned_data로 접근하여 가져 올 수 있다. 그리고 에러를 넣어주고 싶을 경우 form.add_error를 사용하면 된다.

아니면 폼 클래스 내에서 폼 필드에 대해 사용자 정의 유효성 검사를 해줄수 있다.

from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError
User = get_user_model()
class NameForm(forms.Form):
    ...
    
    def clean_<field_name>(self):
    	username = self.cleaned_data['username']
    	if User.objects.filter(username=username).exists():
    	    raise ValidationError('이미 사용중인 아이디 입니다.')
    	return username

Comments