1번째 줄: |
1번째 줄: |
| [[분류:3-1. 장고 폼]] | | [[분류:3-1. 장고 폼]] |
− | 입력값을 바꾸려면... html에서 받을 폼을 수정해주어야 하고, 받을 모델을 변경해주어야 하는 불편함이 있다. 이러한 불편함을 해소하고자 장고에선 장고 form이라는 개념을 제공해 편의성을 제공한다. 폼을 만들고 html에 <nowiki>{{form}}</nowiki> 이라고만 입력하면 자동으로 html 언어로 변환해 보여준다. 모델의 제약 외에 폼에서의 제약을 설정하는 등 상세한 변형이 가능하여 많이 이용되는 개념이다.
| |
| | | |
| + | == 개요 == |
| + | 장고에선 장고 form이라는 개념을 제공해 데이터 입력의 편의성을 제공한다. 장고에서 제공하는, 모델과 연동하여 데이터를 입력받는 기능이다. html을 자동 렌더링해준다. 폼을 통해 DB로의 입력을 제어할 수 있다. |
| | | |
− | 장고에서 제공하는, 데이터를 입력받는 기능이다. html을 자동 렌더링해준다. 폼을 사용하기 위해선 폼 클래스를 정의해야 한다.
| + | 폼을 만들고 html(탬플릿)에 <nowiki>{{form}}</nowiki> 이라고만 입력하면 자동으로 html 언어로 변환해 보여준다. |
| | | |
− | from djangoinport forms | + | 장고는 모델에 따라 적절한 형태의 폼을, 안전하게 처리해주는 기능을 갖고 있다. |
| + | |
| + | 모델의 제약 외에 폼에서의 제약을 설정하는 등 상세한 변형이 가능하여 많이 이용되는 개념이다. |
| + | |
| + | ===폼의 장점=== |
| + | |
| + | * 재활용 할 수 있다. |
| + | * 에러메시지를 자동으로 띄워준다. 탬플릿에 <nowiki>{{ form.error }}</nowiki> 변수를 띄워주면 잘못된 입력이라든가 빈 입력이라든가에 대한 피드백을 해준다. |
| + | * 서로 다른 데이터타입은 유효성 검사(에러검사)도 달리해야 하는데, 이러한 과정을 자동으로 처리해주어 적극 권장한다. |
| + | |
| + | == 정의 == |
| + | 폼을 사용하기 위해선 폼 클래스를 정의해야 한다. |
| + | |
| + | |
| + | |
| + | 일반적으로 앱의 forms.py 안에 정의한다. |
| + | |
| + | === 기본 형태 === |
| + | {| class="wikitable" |
| + | |+ |
| + | ! |
| + | !설명 |
| + | !코드 |
| + | |- |
| + | |모델폼 |
| + | |모델에서 사용하는 제약 그대로 사용할 경우 사용한다. |
| + | |<syntaxhighlight lang="python"> |
| + | from django import forms |
| + | from .models import 모델 # 폼을 적용할 모델을 불러온다. |
| + | |
| + | class 폼이름(forms.ModelForm): # 특별한 경우가 아닌 한 일반폼이 아닌, 모델폼을 사용한다. |
| + | class Meta: |
| + | model = 모델 # 사용할 모델 |
| + | fields = ['필드1', '필드2',...] # 폼으로 입력할 필드를 입력해준다. |
| + | # fields에 '__all__'을 따옴표까지 함께 넣어주면 모든 필드를 가져오라는 명령이 된다. |
| + | </syntaxhighlight>모델폼에선 사용할 모델을 지정하기 위해 메타클래스가 반드시 필요하다. |
| + | |- |
| + | |일반 폼 |
| + | |모델과 별개로 입력값에 대한 유효성검사를 하고 싶을 때 |
| + | (누락, 유효하지 않은 데이터형 등) |
| + | |<syntaxhighlight lang="python"> |
| + | from django import forms |
| | | |
| class 폼이름(forms.Form): | | class 폼이름(forms.Form): |
| + | 속성 = forms.필드명() |
| + | 속성2 = forms.필드명() |
| + | </syntaxhighlight>기본적으로 모델과 같은 필드를 사용한다. 다만, blank, null 속성은 없이, 기본적으로 채워넣어야 하는 값으로 인지한다. |
| + | 속성2 = forms.필드명(required=False) 형태로 넣으면 해당 필드는 비어도 된다는 의미. |
| + | |} |
| + | 대부분 모델과 연동하여 사용하므로 모델 폼을 중심으로 설명한다. |
| + | |
| + | === 폼필드 제약 === |
| + | 클래스 변수로 <code>모델의 속성명 = forms.CharField(label='보여질이름', max_length=100)</code> 따위로 폼 안에서 입력의 제한조건을 걸 수도 있지만, 기왕 모델을 작성하는 거, 모델에서 제한조건을 완성하고 폼에선 보여지는 대상과 방식에 집중하자. |
| + | |
| + | 폼 필드에 일일이 제약을 걸 수는 없으니, 모델에서 제약을 걸고 폼에서는 이를 사용하기만 한다. |
| + | |
| + | 어차피 모델에서 알아서 폼필드를 만든다.(모델은 유효성검사를 하고, 입력 자체를 막진 못한다. 그럴 때 사용하면 된다. 혹은 HTML 코드에서 입력의 제약을 걸 수도 있는데, 각 폼마다 제약을 거는 게 아니라 한번에 <nowiki>{{form}}</nowiki> 형식으로 불러올 거라면 이곳에서 제약을 걸어주어야 한다.) |
| | | |
− | 받을내용=forms.CharField(label='라벨이름', 속성)
| + | ===위젯=== |
− | #각 필드타입에 대해 위젯이 준비되어 있다. 이는 속성으로 들어간다.
| + | 각 폼 필드는 <input type='text'>와 같은 HTML 위젯을 갖고 있다. |
| | | |
| + | 자동으로 태그로 감싸주기 때문에 탬플릿에서 편집이 안된다. 이렇게 되면 디자인측면에서 제약이 생기게 되는데.. 개개 입력칸을 편집하기 위해선 form의 수정이 필요하다. |
| | | |
− | 일반적으로 앱의 forms.py 안에 정의한다.<syntaxhighlight lang="python">
| + | 각 폼필드마다 기본적인 위젯을 갖고 있다. |
| + | |
| + | 폼필드 안의 옵션에 속성=forms.CharFiedl(....., widget={'class'='클래스값', ...}) 와 같이 옵션을 추가해주면 된다.(역시, HTML에서 입력할 수 있기 때문에 분업을 하는 경우 굳이 사용하진 않는다.) |
| + | |
| + | 그런데, 위처럼 작업하면 디자이너가 .py를 만져야 한다는 점에서 디자이너와 개발자간 역할분리가 흐려지기도 한다는 단점이 있다. 이를 탬플릿에서 직접 다루기 위해선 다시 widgets 속성을 없애고, 탬플릿을 수정해준다. 다음과 같은 형식으로 폼 내부의 속성에 접근할 수 있고, 이들을 html에서 직접 편집할 수 있다.<syntaxhighlight lang="html"> |
| + | <label for="subject">제목</label> |
| + | <input type="text" class="form-control" name="subject" id="subject" |
| + | value="{{ form.subject.value|default_if_none:'' }}"> |
| + | </syntaxhighlight><nowiki>{{form.subject}}</nowiki>로 접근할 수 있지만, <nowiki>{{form.subject.value}}</nowiki>를 써준 것은, 에러가 나고 페이지를 새로 불러들일 때 기존 입력값을 보존하기 위함이다. |
| + | |
| + | <nowiki>|</nowiki>default_if_none:<nowiki>''</nowiki> 은 값을 쓰지 않았을 때 <nowiki>''</nowiki>를 담아주기 위한 것. 초기값을 지정할 수도 있다.(이걸 지정하지 않으면 입력하지 않은 값들에 'none'이라는 문자열이 담겨 꼴이 우스워진다) |
| + | |
| + | == 폼 하위함수 == |
| + | {| class="wikitable" |
| + | !의도 |
| + | !설명 |
| + | !코드 |
| + | |- |
| + | |폼 하위함수 |
| + | |모델의 하위함수로 조작이 가능한 것처럼, 폼에서 반복되는 작업은 폼 하위함수로 처리하면 편하다. |
| + | |<syntaxhighlight lang="python"> |
| from django import forms | | from django import forms |
| | | |
| class 폼이름(forms.Form): | | class 폼이름(forms.Form): |
| + | 속성 = forms.필드명() |
| + | 속성2 = forms.필드명() |
| | | |
| + | def 함수(self): |
| + | '''폼에서 받은 변수는 self.cleaned_data에서 얻어올 수 있다.''' |
| + | 명령(self.cleaned_data['속성'], self.cleaned_data['속성2']) |
| </syntaxhighlight> | | </syntaxhighlight> |
− | ===폼필드 제약=== | + | |} |
− | 클래스 변수로 <code>모델의 속성명 = forms.CharField(label='보여질이름', max_length=100)</code> 따위로 폼 안에서 입력의 제한조건을 걸 수도 있지만, 기왕 모델을 작성하는 거, 모델에서 제한조건을 완성하고 폼에선 보여지는 대상과 방식에 집중하자.
| + | == 메타클래스 == |
| + | |
| + | ===폼 라벨 붙이기=== |
| + | 모델에서 사용한 속성 이름이 웹페이지에 그대로 드러나는데, 내부에서 처리하는 변수명과 외부에 드러나는 라벨이 달라야 할 때가 있다. 이 역시 form을 수정함으로써 기능한다.<syntaxhighlight lang="python"> |
| + | class QuestionForm(forms.ModelForm):#모델폼 상속 |
| + | class Meta: |
| + | labels = { # 이 속성의 추가로 나타내는 내용을 표시할 수 있음. |
| + | 'subject': '제목', |
| + | 'content': '내용', |
| + | } |
| | | |
− | 어차피 모델에서 알아서 폼필드를 만든다.(모델은 유효성검사를 하고, 입력 자체를 막진 못한다. 그럴 때 사용하면 된다. 혹은 HTML 코드에서 입력의 제약을 걸 수도 있는데, 각 폼마다 제약을 거는 게 아니라 한번에 <nowiki>{{form}}</nowiki> 형식으로 불러올 거라면 이곳에서 제약을 걸어주어야 한다.)
| + | </syntaxhighlight> |
| | | |
− | 폼 필드에 일일이 제약을 걸 수는 없으니, 모델에서의 제약을 그대로 가져오기도 한다.<syntaxhighlight lang="python">
| + | === 위젯 === |
− | class 폼이름(ModelForm): | + | 필드에서 위젯을 다룰 수도 있지만 메타클래스를 통해 위젯을 다룰 수도 있다. <syntaxhighlight lang="python"> |
| + | class QuestionForm(forms.ModelForm):#모델폼 상속 |
| class Meta: | | class Meta: |
− | model = 사용할 모델 | + | widgets = { #이 속성의 추가로 입력항목에 부트스트랩의 클래스를 추가해 넣을 수 있다. |
− | fields = ['필드1', '필드2',...] # 폼으로 입력할 필드를 입력해준다.
| + | 'subject': forms.TextInput(attrs={'class': 'form-control'}), |
| + | 'content': forms.Textarea(attrs={'class': 'form-control', 'rows': 10}), |
| + | } |
| + | |
| </syntaxhighlight> | | </syntaxhighlight> |
− | ===위젯===
| |
− | 각 폼 필드는 <input type='text'>와 같은 HTML 위젯을 갖고 있다. 각 폼필드마다 기본적인 위젯을 갖고 있다.
| |
− |
| |
− | 폼필드 안의 옵션에 속성=forms.CharFiedl(....., widget={'class'='클래스값', ...}) 와 같이 옵션을 추가해주면 된다.(역시, HTML에서 입력할 수 있기 때문에 분업을 하는 경우 굳이 사용하진 않는다.)
| |