Django Form(장고 폼)
① Form 태그를 쉽게 만들 수 있는 기능
② 유효성 검사 기능
1. ModelForm : Model을 이용한 Form 생성
# forms.py
class NoticeForm(forms.ModelForm): # forms.ModelForm 상속받음
# 필드 추가 (직접 필드를 정의해도 됨)
def __init__(self, *args, **kwargs):
#생략
class Meta:
model = Notice # 모델 연결
fields = ( # 속성나열
'name', 'title', 'content',
)
widgets = { # default값 변경시
'title' : forms.TextInput(attrs={'class': 'form-control'}),
'content' : forms.Textarea(attrs={'class': 'form-control', 'rows': 10}),
}
label = {
'name' : '이름',
'title' : '제목',
'content' : '내용',
}
def save(self, commit=True): # save() 오버라이딩
instance = super().save(commit=False)
#수정예정
return instance
def clean(self): # clean() 오버라이딩
cleaned_data = super().clean()
title = cleaned_data.get('title')
if '[공지]' in title: # ValidationError 커스터마이징
raise ValidationError('해당 문구는 사용할수 없습니다.')
return cleaned_data
# 위의 clean()을 아래와 같이 사용할 수도 있음
def clean_title(self):
title = self.cleaned_data.get('title')
if '[공지]' in title: # ValidationError 커스터마이징
raise ValidationError('해당 문구는 사용할수 없습니다.')
return title
→ 폼을 구현하기 위해서는 forms.ModelForm을 상속 받아야 함
→ ModelForm은 내부클래스인 Meta가 반드시 필요 함
- class Meta
- Meta 클래스 안에 model과 fields를 지정하면 모델폼이 자동으로 폼필드를 생성 함 (model : 모델클래스 연결, fields : 폼에 사용할 속성 나열, label : 변수명 대신 출력시킬 값)
- forms.ModelForm 메서드
- save() :
- clean() : 유효성검사 후 데이터를 받음
- clean_필드명 : 해당 필드만 유효성검사
2. Form
# forms.py
class NoticeForm(forms.Form): # forms.Form 상속받음
name = forms.CharField(max_length=12, required=False, label='이름')
title = forms.CharField(label='제목')
content = forms.CharField(widget=forms.Textarea, lable='내용')
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user') ### view로 부터 user 넘겨받기
super().__init__(*args, **kwargs)
self.fields['name'].widget.attrs.update({'class': 'form-control', 'value' : self.user.first_name})
self.fields['title'].widget.attrs.update({'class': 'form-control'})
def clean(self):
#생략
→ 모델폼과는 다르게 필드를 직접 정의함
- Form 필드 파라미터 (Model 필드 파라미터와 유사)
- max_length : 최대글자수
- required : 필수값
- label : name, title, content와 같은 영어의 변수명 대신에 출력시킬 값
- initial : 폼에서 입력시킬 초기값
- validators : 유효성검사 (유효성 검사는 Model에서 하는걸 추천)
- def __init__(self, *args, **kwargs) : 생성자
- widget.attrs.update() : 위젯 속성값 변경
- forms.Form 메서드
- clean() : 유효성검사
View -> Form 데이터 넘기기
- Form의 생성자의 파라미터로 데이터를 넘기면 됨
View
form = NoticeForm(user = request.user) # GET방식
form = NoticeForm(request.POST, user = request.user) # POST방식
Form
class NoticeForm(forms.Form):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user') # pop을 이용하여 받음
super().__init__(*args, **kwargs)
View
# views.py
from .forms import NoticeForm
from django.shortcuts import redirect
def notice_create(request):
if : request.method == "POST": # POST방식
form = NoticeForm(request.POST, user = request.user)
if form.is_valid():
notice = form.save(commit=False) # 바로 저장하지 않고 꺼내와서 수정함
notice.date = timezone.now()
notice.save() # 저장
return redirect('notice')
else : # GET방식
form = NoticeForm(user = request.user) ### Form으로 user 매개변수 넘기기
context = {'form': form}
return render(request, 'polls/notice.html', context)
→ form 속성에 사용할 폼 명시
→ GET방식일 경우 폼 출력, POST방식일 경우 DB에 저장
→ save(commit=False)를 사용하여 바로 Notice 모델에 저장하지 않고 수정을 할 수 있음
→ 수정이 끝나면 save()를 사용하여 저장
- form.is_valid()
- 검증에 성공한 값들은 사전타입으로 제공 (form.cleaned_data)
- 검증에 실패시 form.error 에 오류 정보를 저장 -> 템플릿에서 object_list.errors 로 출력가능
- form.cleaned_data
- is_valid()를 통해 검증된 값
- dict형태
○ 모델객체에 저장방법
① 디폴트 생성자 사용
if form.is_valid():
notice = Notice()
notice.title = form.cleaned_data['title']
notice.content = form.cleaned_data['content']
notice.save()
② 생성자 사용
if form.is_valid():
notice = Notice(title = form.cleaned_data['title'],
content = form.cleaned_data['content'])
notice.save()
③ create() 사용
if form.is_valid():
notice = Notice.objects.create(title = form.cleaned_data['title'],
content = form.cleaned_data['content'])
Template
<!-- notice_create.html -->
{% extends 'blog/base.html' %}
{% block content %}
<h1>Create Notice</h1>
<form method="POST" class="post-form">
{% csrf_token %}
{{ form.as_p }}
<button class="save btn btn-default">Save</button>
</form>
{% endblock %}
→ {{ form.as_p }} : form의 속성에 맞게 자동으로 html 태그들을 생성시키고 각 항목을 p태그로 감싸서 폼을 만들어 줌
→ {{ form.as_ul }} : ul태그로 감쌈
→ {{ form.as_table }} : table태그로 감쌈
- Form 형태를 커스텀 하고 싶을 경우
{% extends 'blog/base.html' %}
{% block content %}
<h1>Create Notice</h1>
<form method="POST" class="post-form">
{% csrf_token %}
<ul>
<li><label for="name">이름</label></li>
<li>
{{ form.name }}
{{ form.name.errors }
</li>
</ul>
<ul>
<li><label for="title">제목</label></li>
<li>
{{ form.title }}
{{ form.title.errors }
</li>
</ul>
<ul>
<li><label for="content">내용</label></li>
<li>
{{ form.content }}
{{ form.content.errors }
</li>
</ul>
<button class="save btn btn-default">Save</button>
</form>
{% endblock %}
<django official Documentation>
docs.djangoproject.com/en/3.1/ref/forms/fields/
docs.djangoproject.com/en/3.1/ref/forms/api/
docs.djangoproject.com/en/3.1/topics/forms/modelforms/#django.forms.ModelForm